/*!
 * UEditor
 * version: ueditor
 * build: Wed Aug 10 2016 11:06:16 GMT+0800 (CST)
 */
(function() {
    UEDITOR_CONFIG = window.UEDITOR_CONFIG || {};
    var baidu = window.baidu || {};
    window.baidu = baidu;
    window.UE = baidu.editor = window.UE || {};
    UE.plugins = {};
    UE.commands = {};
    UE.instants = {};
    UE.I18N = {};
    UE._customizeUI = {};
    UE.version = "1.4.3";
    var dom = UE.dom = {};
    var browser = UE.browser = function() {
        var agent = navigator.userAgent.toLowerCase(),
            opera = window.opera,
            browser = {
                ie: /(msie\s|trident.*rv:)([\w.]+)/.test(agent),
                opera: ( !! opera && opera.version),
                webkit: (agent.indexOf(" applewebkit/") > -1),
                mac: (agent.indexOf("macintosh") > -1),
                quirks: (document.compatMode == "BackCompat")
            };
        browser.gecko = (navigator.product == "Gecko" && !browser.webkit && !browser.opera && !browser.ie);
        var version = 0;
        if (browser.ie) {
            var v1 = agent.match(/(?:msie\s([\w.]+))/);
            var v2 = agent.match(/(?:trident.*rv:([\w.]+))/);
            if (v1 && v2 && v1[1] && v2[1]) {
                version = Math.max(v1[1] * 1, v2[1] * 1)
            } else {
                if (v1 && v1[1]) {
                    version = v1[1] * 1
                } else {
                    if (v2 && v2[1]) {
                        version = v2[1] * 1
                    } else {
                        version = 0
                    }
                }
            }
            browser.ie11Compat = document.documentMode == 11;
            browser.ie9Compat = document.documentMode == 9;
            browser.ie8 = !! document.documentMode;
            browser.ie8Compat = document.documentMode == 8;
            browser.ie7Compat = ((version == 7 && !document.documentMode) || document.documentMode == 7);
            browser.ie6Compat = (version < 7 || browser.quirks);
            browser.ie9above = version > 8;
            browser.ie9below = version < 9;
            browser.ie11above = version > 10;
            browser.ie11below = version < 11
        }
        if (browser.gecko) {
            var geckoRelease = agent.match(/rv:([\d\.]+)/);
            if (geckoRelease) {
                geckoRelease = geckoRelease[1].split(".");
                version = geckoRelease[0] * 10000 + (geckoRelease[1] || 0) * 100 + (geckoRelease[2] || 0) * 1
            }
        }
        if (/chrome\/(\d+\.\d)/i.test(agent)) {
            browser.chrome = +RegExp["$1"]
        }
        if (/(\d+\.\d)?(?:\.\d)?\s+safari\/?(\d+\.\d+)?/i.test(agent) && !/chrome/i.test(agent)) {
            browser.safari = +(RegExp["$1"] || RegExp["$2"])
        }
        if (browser.opera) {
            version = parseFloat(opera.version())
        }
        if (browser.webkit) {
            version = parseFloat(agent.match(/ applewebkit\/(\d+)/)[1])
        }
        browser.version = version;
        browser.isCompatible = !browser.mobile && ((browser.ie && version >= 6) || (browser.gecko && version >= 10801) || (browser.opera && version >= 9.5) || (browser.air && version >= 1) || (browser.webkit && version >= 522) || false);
        return browser
    }();
    var ie = browser.ie,
        webkit = browser.webkit,
        gecko = browser.gecko,
        opera = browser.opera;
    var utils = UE.utils = {
        each: function(obj, iterator, context) {
            if (obj == null) {
                return
            }
            if (obj.length === +obj.length) {
                for (var i = 0, l = obj.length; i < l; i++) {
                    if (iterator.call(context, obj[i], i, obj) === false) {
                        return false
                    }
                }
            } else {
                for (var key in obj) {
                    if (obj.hasOwnProperty(key)) {
                        if (iterator.call(context, obj[key], key, obj) === false) {
                            return false
                        }
                    }
                }
            }
        },
        makeInstance: function(obj) {
            var noop = new Function();
            noop.prototype = obj;
            obj = new noop;
            noop.prototype = null;
            return obj
        },
        extend: function(t, s, b) {
            if (s) {
                for (var k in s) {
                    if (!b || !t.hasOwnProperty(k)) {
                        t[k] = s[k]
                    }
                }
            }
            return t
        },
        extend2: function(t) {
            var a = arguments;
            for (var i = 1; i < a.length; i++) {
                var x = a[i];
                for (var k in x) {
                    if (!t.hasOwnProperty(k)) {
                        t[k] = x[k]
                    }
                }
            }
            return t
        },
        inherits: function(subClass, superClass) {
            var oldP = subClass.prototype,
                newP = utils.makeInstance(superClass.prototype);
            utils.extend(newP, oldP, true);
            subClass.prototype = newP;
            return (newP.constructor = subClass)
        },
        bind: function(fn, context) {
            return function() {
                return fn.apply(context, arguments)
            }
        },
        defer: function(fn, delay, exclusion) {
            var timerID;
            return function() {
                if (exclusion) {
                    clearTimeout(timerID)
                }
                timerID = setTimeout(fn, delay)
            }
        },
        indexOf: function(array, item, start) {
            var index = -1;
            start = this.isNumber(start) ? start : 0;
            this.each(array, function(v, i) {
                if (i >= start && v === item) {
                    index = i;
                    return false
                }
            });
            return index
        },
        removeItem: function(array, item) {
            for (var i = 0, l = array.length; i < l; i++) {
                if (array[i] === item) {
                    array.splice(i, 1);
                    i--
                }
            }
        },
        trim: function(str) {
            return str.replace(/(^[ \t\n\r]+)|([ \t\n\r]+$)/g, "")
        },
        listToMap: function(list) {
            if (!list) {
                return {}
            }
            list = utils.isArray(list) ? list : list.split(",");
            for (var i = 0, ci, obj = {}; ci = list[i++];) {
                obj[ci.toUpperCase()] = obj[ci] = 1
            }
            return obj
        },
        unhtml: function(str, reg) {
            return str ? str.replace(reg || /[&<">'](?:(amp|lt|quot|gt|#39|nbsp|#\d+);)?/g, function(a, b) {
                if (b) {
                    return a
                } else {
                    return {
                        "<": "&lt;",
                        "&": "&amp;",
                        '"': "&quot;",
                        ">": "&gt;",
                        "'": "&#39;"
                    }[a]
                }
            }) : ""
        },
        unhtmlForUrl: function(str, reg) {
            return str ? str.replace(reg || /[<">']/g, function(a) {
                return {
                    "<": "&lt;",
                    "&": "&amp;",
                    '"': "&quot;",
                    ">": "&gt;",
                    "'": "&#39;"
                }[a]
            }) : ""
        },
        html: function(str) {
            return str ? str.replace(/&((g|l|quo)t|amp|#39|nbsp);/g, function(m) {
                return {
                    "&lt;": "<",
                    "&amp;": "&",
                    "&quot;": '"',
                    "&gt;": ">",
                    "&#39;": "'",
                    "&nbsp;": " "
                }[m]
            }) : ""
        },
        cssStyleToDomStyle: function() {
            var test = document.createElement("div").style,
                cache = {
                    "float": test.cssFloat != undefined ? "cssFloat" : test.styleFloat != undefined ? "styleFloat" : "float"
                };
            return function(cssName) {
                return cache[cssName] || (cache[cssName] = cssName.toLowerCase().replace(/-./g, function(match) {
                    return match.charAt(1).toUpperCase()
                }))
            }
        }(),
        loadFile: function() {
            var tmpList = [];

            function getItem(doc, obj) {
                try {
                    for (var i = 0, ci; ci = tmpList[i++];) {
                        if (ci.doc === doc && ci.url == (obj.src || obj.href)) {
                            return ci
                        }
                    }
                } catch (e) {
                    return null
                }
            }
            return function(doc, obj, fn) {
                var item = getItem(doc, obj);
                if (item) {
                    if (item.ready) {
                        fn && fn()
                    } else {
                        item.funs.push(fn)
                    }
                    return
                }
                tmpList.push({
                    doc: doc,
                    url: obj.src || obj.href,
                    funs: [fn]
                });
                if (!doc.body) {
                    var html = [];
                    for (var p in obj) {
                        if (p == "tag") {
                            continue
                        }
                        html.push(p + '="' + obj[p] + '"')
                    }
                    doc.write("<" + obj.tag + " " + html.join(" ") + " ></" + obj.tag + ">");
                    return
                }
                if (obj.id && doc.getElementById(obj.id)) {
                    return
                }
                var element = doc.createElement(obj.tag);
                delete obj.tag;
                for (var p in obj) {
                    element.setAttribute(p, obj[p])
                }
                element.onload = element.onreadystatechange = function() {
                    if (!this.readyState || /loaded|complete/.test(this.readyState)) {
                        item = getItem(doc, obj);
                        if (item.funs.length > 0) {
                            item.ready = 1;
                            for (var fi; fi = item.funs.pop();) {
                                fi()
                            }
                        }
                        element.onload = element.onreadystatechange = null
                    }
                };
                element.onerror = function() {
                    throw Error("The load " + (obj.href || obj.src) + " fails,check the url settings of file ueditor.config.js ")
                };
                doc.getElementsByTagName("head")[0].appendChild(element)
            }
        }(),
        isEmptyObject: function(obj) {
            if (obj == null) {
                return true
            }
            if (this.isArray(obj) || this.isString(obj)) {
                return obj.length === 0
            }
            for (var key in obj) {
                if (obj.hasOwnProperty(key)) {
                    return false
                }
            }
            return true
        },
        fixColor: function(name, value) {
            if (/color/i.test(name) && /rgba?/.test(value)) {
                var array = value.split(",");
                if (array.length > 3) {
                    return ""
                }
                value = "#";
                for (var i = 0, color; color = array[i++];) {
                    color = parseInt(color.replace(/[^\d]/gi, ""), 10).toString(16);
                    value += color.length == 1 ? "0" + color : color
                }
                value = value.toUpperCase()
            }
            return value
        },
        optCss: function(val) {
            var padding, margin, border;
            val = val.replace(/(padding|margin|border)\-([^:]+):([^;]+);?/gi, function(str, key, name, val) {
                if (val.split(" ").length == 1) {
                    switch (key) {
                        case "padding":
                            !padding && (padding = {});
                            padding[name] = val;
                            return "";
                        case "margin":
                            !margin && (margin = {});
                            margin[name] = val;
                            return "";
                        case "border":
                            return val == "initial" ? "" : str
                    }
                }
                return str
            });

            function opt(obj, name) {
                if (!obj) {
                    return ""
                }
                var t = obj.top,
                    b = obj.bottom,
                    l = obj.left,
                    r = obj.right,
                    val = "";
                if (!t || !l || !b || !r) {
                    for (var p in obj) {
                        val += ";" + name + "-" + p + ":" + obj[p] + ";"
                    }
                } else {
                    val += ";" + name + ":" + (t == b && b == l && l == r ? t : t == b && l == r ? (t + " " + l) : l == r ? (t + " " + l + " " + b) : (t + " " + r + " " + b + " " + l)) + ";"
                }
                return val
            }
            val += opt(padding, "padding") + opt(margin, "margin");
            return val.replace(/^[ \n\r\t;]*|[ \n\r\t]*$/, "").replace(/;([ \n\r\t]+)|\1;/g, ";").replace(/(&((l|g)t|quot|#39))?;{2,}/g, function(a, b) {
                return b ? b + ";;" : ";"
            })
        },
        clone: function(source, target) {
            var tmp;
            target = target || {};
            for (var i in source) {
                if (source.hasOwnProperty(i)) {
                    tmp = source[i];
                    if (typeof tmp == "object") {
                        target[i] = utils.isArray(tmp) ? [] : {};
                        utils.clone(source[i], target[i])
                    } else {
                        target[i] = tmp
                    }
                }
            }
            return target
        },
        transUnitToPx: function(val) {
            if (!/(pt|cm)/.test(val)) {
                return val
            }
            var unit;
            val.replace(/([\d.]+)(\w+)/, function(str, v, u) {
                val = v;
                unit = u
            });
            switch (unit) {
                case "cm":
                    val = parseFloat(val) * 25;
                    break;
                case "pt":
                    val = Math.round(parseFloat(val) * 96 / 72)
            }
            return val + (val ? "px" : "")
        },
        domReady: function() {
            var fnArr = [];

            function doReady(doc) {
                doc.isReady = true;
                for (var ci; ci = fnArr.pop(); ci()) {}
            }
            return function(onready, win) {
                win = win || window;
                var doc = win.document;
                onready && fnArr.push(onready);
                if (doc.readyState === "complete") {
                    doReady(doc)
                } else {
                    doc.isReady && doReady(doc);
                    if (browser.ie && browser.version != 11) {
                        (function() {
                            if (doc.isReady) {
                                return
                            }
                            try {
                                doc.documentElement.doScroll("left")
                            } catch (error) {
                                setTimeout(arguments.callee, 0);
                                return
                            }
                            doReady(doc)
                        })();
                        win.attachEvent("onload", function() {
                            doReady(doc)
                        })
                    } else {
                        doc.addEventListener("DOMContentLoaded", function() {
                            doc.removeEventListener("DOMContentLoaded", arguments.callee, false);
                            doReady(doc)
                        }, false);
                        win.addEventListener("load", function() {
                            doReady(doc)
                        }, false)
                    }
                }
            }
        }(),
        cssRule: browser.ie && browser.version != 11 ?
            function(key, style, doc) {
                var indexList, index;
                if (style === undefined || style && style.nodeType && style.nodeType == 9) {
                    doc = style && style.nodeType && style.nodeType == 9 ? style : (doc || document);
                    indexList = doc.indexList || (doc.indexList = {});
                    index = indexList[key];
                    if (index !== undefined) {
                        return doc.styleSheets[index].cssText
                    }
                    return undefined
                }
                doc = doc || document;
                indexList = doc.indexList || (doc.indexList = {});
                index = indexList[key];
                if (style === "") {
                    if (index !== undefined) {
                        doc.styleSheets[index].cssText = "";
                        delete indexList[key];
                        return true
                    }
                    return false
                }
                if (index !== undefined) {
                    sheetStyle = doc.styleSheets[index]
                } else {
                    sheetStyle = doc.createStyleSheet("", index = doc.styleSheets.length);
                    indexList[key] = index
                }
                sheetStyle.cssText = style
            } : function(key, style, doc) {
                var head, node;
                if (style === undefined || style && style.nodeType && style.nodeType == 9) {
                    doc = style && style.nodeType && style.nodeType == 9 ? style : (doc || document);
                    node = doc.getElementById(key);
                    return node ? node.innerHTML : undefined
                }
                doc = doc || document;
                node = doc.getElementById(key);
                if (style === "") {
                    if (node) {
                        node.parentNode.removeChild(node);
                        return true
                    }
                    return false
                }
                if (node) {
                    node.innerHTML = style
                } else {
                    node = doc.createElement("style");
                    node.id = key;
                    node.innerHTML = style;
                    doc.getElementsByTagName("head")[0].appendChild(node)
                }
            },
        sort: function(array, compareFn) {
            compareFn = compareFn ||
                function(item1, item2) {
                    return item1.localeCompare(item2)
                };
            for (var i = 0, len = array.length; i < len; i++) {
                for (var j = i, length = array.length; j < length; j++) {
                    if (compareFn(array[i], array[j]) > 0) {
                        var t = array[i];
                        array[i] = array[j];
                        array[j] = t
                    }
                }
            }
            return array
        },
        serializeParam: function(json) {
            var strArr = [];
            for (var i in json) {
                if (i == "method" || i == "timeout" || i == "async") {
                    continue
                }
                if (!((typeof json[i]).toLowerCase() == "function" || (typeof json[i]).toLowerCase() == "object")) {
                    strArr.push(encodeURIComponent(i) + "=" + encodeURIComponent(json[i]))
                } else {
                    if (utils.isArray(json[i])) {
                        for (var j = 0; j < json[i].length; j++) {
                            strArr.push(encodeURIComponent(i) + "[]=" + encodeURIComponent(json[i][j]))
                        }
                    }
                }
            }
            return strArr.join("&")
        },
        formatUrl: function(url) {
            var u = url.replace(/&&/g, "&");
            u = u.replace(/\?&/g, "?");
            u = u.replace(/&$/g, "");
            u = u.replace(/&#/g, "#");
            u = u.replace(/&+/g, "&");
            return u
        },
        isCrossDomainUrl: function(url) {
            var a = document.createElement("a");
            a.href = url;
            if (browser.ie) {
                a.href = a.href
            }
            return !(a.protocol == location.protocol && a.hostname == location.hostname && (a.port == location.port || (a.port == "80" && location.port == "") || (a.port == "" && location.port == "80")))
        },
        clearEmptyAttrs: function(obj) {
            for (var p in obj) {
                if (obj[p] === "") {
                    delete obj[p]
                }
            }
            return obj
        },
        str2json: function(s) {
            if (!utils.isString(s)) {
                return null
            }
            if (window.JSON) {
                return JSON.parse(s)
            } else {
                return (new Function("return " + utils.trim(s || "")))()
            }
        },
        json2str: (function() {
            if (window.JSON) {
                return JSON.stringify
            } else {
                var escapeMap = {
                    "\b": "\\b",
                    "\t": "\\t",
                    "\n": "\\n",
                    "\f": "\\f",
                    "\r": "\\r",
                    '"': '\\"',
                    "\\": "\\\\"
                };

                function encodeString(source) {
                    if (/["\\-]/.test(source)) {
                        source = source.replace(/["\\-]/g, function(match) {
                            var c = escapeMap[match];
                            if (c) {
                                return c
                            }
                            c = match.charCodeAt();
                            return "\\u00" + Math.floor(c / 16).toString(16) + (c % 16).toString(16)
                        })
                    }
                    return '"' + source + '"'
                }
                function encodeArray(source) {
                    var result = ["["],
                        l = source.length,
                        preComma, i, item;
                    for (i = 0; i < l; i++) {
                        item = source[i];
                        switch (typeof item) {
                            case "undefined":
                            case "function":
                            case "unknown":
                                break;
                            default:
                                if (preComma) {
                                    result.push(",")
                                }
                                result.push(utils.json2str(item));
                                preComma = 1
                        }
                    }
                    result.push("]");
                    return result.join("")
                }
                function pad(source) {
                    return source < 10 ? "0" + source : source
                }
                function encodeDate(source) {
                    return '"' + source.getFullYear() + "-" + pad(source.getMonth() + 1) + "-" + pad(source.getDate()) + "T" + pad(source.getHours()) + ":" + pad(source.getMinutes()) + ":" + pad(source.getSeconds()) + '"'
                }
                return function(value) {
                    switch (typeof value) {
                        case "undefined":
                            return "undefined";
                        case "number":
                            return isFinite(value) ? String(value) : "null";
                        case "string":
                            return encodeString(value);
                        case "boolean":
                            return String(value);
                        default:
                            if (value === null) {
                                return "null"
                            } else {
                                if (utils.isArray(value)) {
                                    return encodeArray(value)
                                } else {
                                    if (utils.isDate(value)) {
                                        return encodeDate(value)
                                    } else {
                                        var result = ["{"],
                                            encode = utils.json2str,
                                            preComma, item;
                                        for (var key in value) {
                                            if (Object.prototype.hasOwnProperty.call(value, key)) {
                                                item = value[key];
                                                switch (typeof item) {
                                                    case "undefined":
                                                    case "unknown":
                                                    case "function":
                                                        break;
                                                    default:
                                                        if (preComma) {
                                                            result.push(",")
                                                        }
                                                        preComma = 1;
                                                        result.push(encode(key) + ":" + encode(item))
                                                }
                                            }
                                        }
                                        result.push("}");
                                        return result.join("")
                                    }
                                }
                            }
                    }
                }
            }
        })()
    };
    utils.each(["String", "Function", "Array", "Number", "RegExp", "Object", "Date"], function(v) {
        UE.utils["is" + v] = function(obj) {
            return Object.prototype.toString.apply(obj) == "[object " + v + "]"
        }
    });
    var EventBase = UE.EventBase = function() {};
    EventBase.prototype = {
        addListener: function(types, listener) {
            types = utils.trim(types).split(/\s+/);
            for (var i = 0, ti; ti = types[i++];) {
                getListener(this, ti, true).push(listener)
            }
        },
        on: function(types, listener) {
            return this.addListener(types, listener)
        },
        off: function(types, listener) {
            return this.removeListener(types, listener)
        },
        trigger: function() {
            return this.fireEvent.apply(this, arguments)
        },
        removeListener: function(types, listener) {
            types = utils.trim(types).split(/\s+/);
            for (var i = 0, ti; ti = types[i++];) {
                utils.removeItem(getListener(this, ti) || [], listener)
            }
        },
        fireEvent: function() {
            var types = arguments[0];
            types = utils.trim(types).split(" ");
            for (var i = 0, ti; ti = types[i++];) {
                var listeners = getListener(this, ti),
                    r, t, k;
                if (listeners) {
                    k = listeners.length;
                    while (k--) {
                        if (!listeners[k]) {
                            continue
                        }
                        t = listeners[k].apply(this, arguments);
                        if (t === true) {
                            return t
                        }
                        if (t !== undefined) {
                            r = t
                        }
                    }
                }
                if (t = this["on" + ti.toLowerCase()]) {
                    r = t.apply(this, arguments)
                }
            }
            return r
        }
    };

    function getListener(obj, type, force) {
        var allListeners;
        type = type.toLowerCase();
        return ((allListeners = (obj.__allListeners || force && (obj.__allListeners = {}))) && (allListeners[type] || force && (allListeners[type] = [])))
    }
    var dtd = dom.dtd = (function() {
        function _(s) {
            for (var k in s) {
                s[k.toUpperCase()] = s[k]
            }
            return s
        }
        var X = utils.extend2;
        var A = _({
                isindex: 1,
                fieldset: 1
            }),
            B = _({
                input: 1,
                button: 1,
                select: 1,
                textarea: 1,
                label: 1
            }),
            C = X(_({
                a: 1
            }), B),
            D = X({
                iframe: 1
            }, C),
            E = _({
                hr: 1,
                ul: 1,
                menu: 1,
                div: 1,
                blockquote: 1,
                noscript: 1,
                table: 1,
                center: 1,
                address: 1,
                dir: 1,
                pre: 1,
                h5: 1,
                dl: 1,
                h4: 1,
                noframes: 1,
                h6: 1,
                ol: 1,
                h1: 1,
                h3: 1,
                h2: 1
            }),
            F = _({
                ins: 1,
                del: 1,
                script: 1,
                style: 1
            }),
            G = X(_({
                b: 1,
                acronym: 1,
                bdo: 1,
                "var": 1,
                "#": 1,
                abbr: 1,
                code: 1,
                br: 1,
                i: 1,
                cite: 1,
                kbd: 1,
                u: 1,
                strike: 1,
                s: 1,
                tt: 1,
                strong: 1,
                q: 1,
                samp: 1,
                em: 1,
                dfn: 1,
                span: 1
            }), F),
            H = X(_({
                sub: 1,
                img: 1,
                embed: 1,
                object: 1,
                sup: 1,
                basefont: 1,
                map: 1,
                applet: 1,
                font: 1,
                big: 1,
                small: 1
            }), G),
            I = X(_({
                p: 1
            }), H),
            J = X(_({
                iframe: 1
            }), H, B),
            K = _({
                img: 1,
                embed: 1,
                noscript: 1,
                br: 1,
                kbd: 1,
                center: 1,
                button: 1,
                basefont: 1,
                h5: 1,
                h4: 1,
                samp: 1,
                h6: 1,
                ol: 1,
                h1: 1,
                h3: 1,
                h2: 1,
                form: 1,
                font: 1,
                "#": 1,
                select: 1,
                menu: 1,
                ins: 1,
                abbr: 1,
                label: 1,
                code: 1,
                table: 1,
                script: 1,
                cite: 1,
                input: 1,
                iframe: 1,
                strong: 1,
                textarea: 1,
                noframes: 1,
                big: 1,
                small: 1,
                span: 1,
                hr: 1,
                sub: 1,
                bdo: 1,
                "var": 1,
                div: 1,
                object: 1,
                sup: 1,
                strike: 1,
                dir: 1,
                map: 1,
                dl: 1,
                applet: 1,
                del: 1,
                isindex: 1,
                fieldset: 1,
                ul: 1,
                b: 1,
                acronym: 1,
                a: 1,
                blockquote: 1,
                i: 1,
                u: 1,
                s: 1,
                tt: 1,
                address: 1,
                q: 1,
                pre: 1,
                p: 1,
                em: 1,
                dfn: 1
            }),
            L = X(_({
                a: 0
            }), J),
            M = _({
                tr: 1
            }),
            N = _({
                "#": 1
            }),
            O = X(_({
                param: 1
            }), K),
            P = X(_({
                form: 1
            }), A, D, E, I),
            Q = _({
                li: 1,
                ol: 1,
                ul: 1
            }),
            R = _({
                style: 1,
                script: 1
            }),
            S = _({
                base: 1,
                link: 1,
                meta: 1,
                title: 1
            }),
            T = X(S, R),
            U = _({
                head: 1,
                body: 1
            }),
            V = _({
                html: 1
            });
        var block = _({
                address: 1,
                blockquote: 1,
                center: 1,
                dir: 1,
                div: 1,
                dl: 1,
                fieldset: 1,
                form: 1,
                h1: 1,
                h2: 1,
                h3: 1,
                h4: 1,
                h5: 1,
                h6: 1,
                hr: 1,
                isindex: 1,
                menu: 1,
                noframes: 1,
                ol: 1,
                p: 1,
                pre: 1,
                table: 1,
                ul: 1
            }),
            empty = _({
                area: 1,
                base: 1,
                basefont: 1,
                br: 1,
                col: 1,
                command: 1,
                dialog: 1,
                embed: 1,
                hr: 1,
                img: 1,
                input: 1,
                isindex: 1,
                keygen: 1,
                link: 1,
                meta: 1,
                param: 1,
                source: 1,
                track: 1,
                wbr: 1
            });
        return _({
            $nonBodyContent: X(V, U, S),
            $block: block,
            $inline: L,
            $inlineWithA: X(_({
                a: 1
            }), L),
            $body: X(_({
                script: 1,
                style: 1
            }), block),
            $cdata: _({
                script: 1,
                style: 1
            }),
            $empty: empty,
            $nonChild: _({
                iframe: 1,
                textarea: 1
            }),
            $listItem: _({
                dd: 1,
                dt: 1,
                li: 1
            }),
            $list: _({
                ul: 1,
                ol: 1,
                dl: 1
            }),
            $isNotEmpty: _({
                table: 1,
                ul: 1,
                ol: 1,
                dl: 1,
                iframe: 1,
                area: 1,
                base: 1,
                col: 1,
                hr: 1,
                img: 1,
                embed: 1,
                input: 1,
                link: 1,
                meta: 1,
                param: 1,
                h1: 1,
                h2: 1,
                h3: 1,
                h4: 1,
                h5: 1,
                h6: 1
            }),
            $removeEmpty: _({
                a: 1,
                abbr: 1,
                acronym: 1,
                address: 1,
                b: 1,
                bdo: 1,
                big: 1,
                cite: 1,
                code: 1,
                del: 1,
                dfn: 1,
                em: 1,
                font: 1,
                i: 1,
                ins: 1,
                label: 1,
                kbd: 1,
                q: 1,
                s: 1,
                samp: 1,
                small: 1,
                span: 1,
                strike: 1,
                strong: 1,
                sub: 1,
                sup: 1,
                tt: 1,
                u: 1,
                "var": 1
            }),
            $removeEmptyBlock: _({
                "p": 1,
                "div": 1
            }),
            $tableContent: _({
                caption: 1,
                col: 1,
                colgroup: 1,
                tbody: 1,
                td: 1,
                tfoot: 1,
                th: 1,
                thead: 1,
                tr: 1,
                table: 1
            }),
            $notTransContent: _({
                pre: 1,
                script: 1,
                style: 1,
                textarea: 1
            }),
            html: U,
            head: T,
            style: N,
            script: N,
            body: P,
            base: {},
            link: {},
            meta: {},
            title: N,
            col: {},
            tr: _({
                td: 1,
                th: 1
            }),
            img: {},
            embed: {},
            colgroup: _({
                thead: 1,
                col: 1,
                tbody: 1,
                tr: 1,
                tfoot: 1
            }),
            noscript: P,
            td: P,
            br: {},
            th: P,
            center: P,
            kbd: L,
            button: X(I, E),
            basefont: {},
            h5: L,
            h4: L,
            samp: L,
            h6: L,
            ol: Q,
            h1: L,
            h3: L,
            option: N,
            h2: L,
            form: X(A, D, E, I),
            select: _({
                optgroup: 1,
                option: 1
            }),
            font: L,
            ins: L,
            menu: Q,
            abbr: L,
            label: L,
            table: _({
                thead: 1,
                col: 1,
                tbody: 1,
                tr: 1,
                colgroup: 1,
                caption: 1,
                tfoot: 1
            }),
            code: L,
            tfoot: M,
            cite: L,
            li: P,
            input: {},
            iframe: P,
            strong: L,
            textarea: N,
            noframes: P,
            big: L,
            small: L,
            span: _({
                "#": 1,
                br: 1,
                b: 1,
                strong: 1,
                u: 1,
                i: 1,
                em: 1,
                sub: 1,
                sup: 1,
                strike: 1,
                span: 1
            }),
            hr: L,
            dt: L,
            sub: L,
            optgroup: _({
                option: 1
            }),
            param: {},
            bdo: L,
            "var": L,
            div: P,
            object: O,
            sup: L,
            dd: P,
            strike: L,
            area: {},
            dir: Q,
            map: X(_({
                area: 1,
                form: 1,
                p: 1
            }), A, F, E),
            applet: O,
            dl: _({
                dt: 1,
                dd: 1
            }),
            del: L,
            isindex: {},
            fieldset: X(_({
                legend: 1
            }), K),
            thead: M,
            ul: Q,
            acronym: L,
            b: L,
            a: X(_({
                a: 1
            }), J),
            blockquote: X(_({
                td: 1,
                tr: 1,
                tbody: 1,
                li: 1
            }), P),
            caption: L,
            i: L,
            u: L,
            tbody: M,
            s: L,
            address: X(D, I),
            tt: L,
            legend: L,
            q: L,
            pre: X(G, C),
            p: X(_({
                "a": 1
            }), L),
            em: L,
            dfn: L
        })
    })();

    function getDomNode(node, start, ltr, startFromChild, fn, guard) {
        var tmpNode = startFromChild && node[start],
            parent;
        !tmpNode && (tmpNode = node[ltr]);
        while (!tmpNode && (parent = (parent || node).parentNode)) {
            if (parent.tagName == "BODY" || guard && !guard(parent)) {
                return null
            }
            tmpNode = parent[ltr]
        }
        if (tmpNode && fn && !fn(tmpNode)) {
            return getDomNode(tmpNode, start, ltr, false, fn)
        }
        return tmpNode
    }
    var attrFix = ie && browser.version < 9 ? {
            tabindex: "tabIndex",
            readonly: "readOnly",
            "for": "htmlFor",
            "class": "className",
            maxlength: "maxLength",
            cellspacing: "cellSpacing",
            cellpadding: "cellPadding",
            rowspan: "rowSpan",
            colspan: "colSpan",
            usemap: "useMap",
            frameborder: "frameBorder"
        } : {
            tabindex: "tabIndex",
            readonly: "readOnly"
        },
        styleBlock = utils.listToMap(["-webkit-box", "-moz-box", "block", "list-item", "table", "table-row-group", "table-header-group", "table-footer-group", "table-row", "table-column-group", "table-column", "table-cell", "table-caption"]);
    var domUtils = dom.domUtils = {
        NODE_ELEMENT: 1,
        NODE_DOCUMENT: 9,
        NODE_TEXT: 3,
        NODE_COMMENT: 8,
        NODE_DOCUMENT_FRAGMENT: 11,
        POSITION_IDENTICAL: 0,
        POSITION_DISCONNECTED: 1,
        POSITION_FOLLOWING: 2,
        POSITION_PRECEDING: 4,
        POSITION_IS_CONTAINED: 8,
        POSITION_CONTAINS: 16,
        fillChar: ie && browser.version == "6" ? "﻿" : "​",
        keys: {
            8: 1,
            46: 1,
            16: 1,
            17: 1,
            18: 1,
            37: 1,
            38: 1,
            39: 1,
            40: 1,
            13: 1
        },
        getPosition: function(nodeA, nodeB) {
            if (nodeA === nodeB) {
                return 0
            }
            var node, parentsA = [nodeA],
                parentsB = [nodeB];
            node = nodeA;
            while (node = node.parentNode) {
                if (node === nodeB) {
                    return 10
                }
                parentsA.push(node)
            }
            node = nodeB;
            while (node = node.parentNode) {
                if (node === nodeA) {
                    return 20
                }
                parentsB.push(node)
            }
            parentsA.reverse();
            parentsB.reverse();
            if (parentsA[0] !== parentsB[0]) {
                return 1
            }
            var i = -1;
            while (i++, parentsA[i] === parentsB[i]) {}
            nodeA = parentsA[i];
            nodeB = parentsB[i];
            while (nodeA = nodeA.nextSibling) {
                if (nodeA === nodeB) {
                    return 4
                }
            }
            return 2
        },
        getNodeIndex: function(node, ignoreTextNode) {
            var preNode = node,
                i = 0;
            while (preNode = preNode.previousSibling) {
                if (ignoreTextNode && preNode.nodeType == 3) {
                    if (preNode.nodeType != preNode.nextSibling.nodeType) {
                        i++
                    }
                    continue
                }
                i++
            }
            return i
        },
        inDoc: function(node, doc) {
            return domUtils.getPosition(node, doc) == 10
        },
        findParent: function(node, filterFn, includeSelf) {
            if (node && !domUtils.isBody(node)) {
                node = includeSelf ? node : node.parentNode;
                while (node) {
                    if (!filterFn || filterFn(node) || domUtils.isBody(node)) {
                        return filterFn && !filterFn(node) && domUtils.isBody(node) ? null : node
                    }
                    node = node.parentNode
                }
            }
            return null
        },
        findParentByTagName: function(node, tagNames, includeSelf, excludeFn) {
            tagNames = utils.listToMap(utils.isArray(tagNames) ? tagNames : [tagNames]);
            return domUtils.findParent(node, function(node) {
                return tagNames[node.tagName] && !(excludeFn && excludeFn(node))
            }, includeSelf)
        },
        findParents: function(node, includeSelf, filterFn, closerFirst) {
            var parents = includeSelf && (filterFn && filterFn(node) || !filterFn) ? [node] : [];
            while (node = domUtils.findParent(node, filterFn)) {
                parents.push(node)
            }
            return closerFirst ? parents : parents.reverse()
        },
        insertAfter: function(node, newNode) {
            return node.nextSibling ? node.parentNode.insertBefore(newNode, node.nextSibling) : node.parentNode.appendChild(newNode)
        },
        remove: function(node, keepChildren) {
            var parent = node.parentNode,
                child;
            if (parent) {
                if (keepChildren && node.hasChildNodes()) {
                    while (child = node.firstChild) {
                        parent.insertBefore(child, node)
                    }
                }
                parent.removeChild(node)
            }
            return node
        },
        getNextDomNode: function(node, startFromChild, filterFn, guard) {
            return getDomNode(node, "firstChild", "nextSibling", startFromChild, filterFn, guard)
        },
        getPreDomNode: function(node, startFromChild, filterFn, guard) {
            return getDomNode(node, "lastChild", "previousSibling", startFromChild, filterFn, guard)
        },
        isBookmarkNode: function(node) {
            return node.nodeType == 1 && node.id && /^_baidu_bookmark_/i.test(node.id)
        },
        getWindow: function(node) {
            var doc = node.ownerDocument || node;
            return doc.defaultView || doc.parentWindow
        },
        getCommonAncestor: function(nodeA, nodeB) {
            if (nodeA === nodeB) {
                return nodeA
            }
            var parentsA = [nodeA],
                parentsB = [nodeB],
                parent = nodeA,
                i = -1;
            while (parent = parent.parentNode) {
                if (parent === nodeB) {
                    return parent
                }
                parentsA.push(parent)
            }
            parent = nodeB;
            while (parent = parent.parentNode) {
                if (parent === nodeA) {
                    return parent
                }
                parentsB.push(parent)
            }
            parentsA.reverse();
            parentsB.reverse();
            while (i++, parentsA[i] === parentsB[i]) {}
            return i == 0 ? null : parentsA[i - 1]
        },
        clearEmptySibling: function(node, ignoreNext, ignorePre) {
            function clear(next, dir) {
                var tmpNode;
                while (next && !domUtils.isBookmarkNode(next) && (domUtils.isEmptyInlineElement(next) || !new RegExp("[^\t\n\r" + domUtils.fillChar + "]").test(next.nodeValue))) {
                    tmpNode = next[dir];
                    domUtils.remove(next);
                    next = tmpNode
                }
            }!ignoreNext && clear(node.nextSibling, "nextSibling");
            !ignorePre && clear(node.previousSibling, "previousSibling")
        },
        split: function(node, offset) {
            var doc = node.ownerDocument;
            if (browser.ie && offset == node.nodeValue.length) {
                var next = doc.createTextNode("");
                return domUtils.insertAfter(node, next)
            }
            var retval = node.splitText(offset);
            if (browser.ie8) {
                var tmpNode = doc.createTextNode("");
                domUtils.insertAfter(retval, tmpNode);
                domUtils.remove(tmpNode)
            }
            return retval
        },
        isWhitespace: function(node) {
            return !new RegExp("[^ \t\n\r" + domUtils.fillChar + "]").test(node.nodeValue)
        },
        getXY: function(element) {
            var x = 0,
                y = 0;
            while (element.offsetParent) {
                y += element.offsetTop;
                x += element.offsetLeft;
                element = element.offsetParent
            }
            return {
                "x": x,
                "y": y
            }
        },
        on: function(element, type, handler) {
            var types = utils.isArray(type) ? type : utils.trim(type).split(/\s+/),
                k = types.length;
            if (k) {
                while (k--) {
                    type = types[k];
                    if (element.addEventListener) {
                        element.addEventListener(type, handler, false)
                    } else {
                        if (!handler._d) {
                            handler._d = {
                                els: []
                            }
                        }
                        var key = type + handler.toString(),
                            index = utils.indexOf(handler._d.els, element);
                        if (!handler._d[key] || index == -1) {
                            if (index == -1) {
                                handler._d.els.push(element)
                            }
                            if (!handler._d[key]) {
                                handler._d[key] = function(evt) {
                                    return handler.call(evt.srcElement, evt || window.event)
                                }
                            }
                            element.attachEvent("on" + type, handler._d[key])
                        }
                    }
                }
            }
            element = null
        },
        un: function(element, type, handler) {
            var types = utils.isArray(type) ? type : utils.trim(type).split(/\s+/),
                k = types.length;
            if (k) {
                while (k--) {
                    type = types[k];
                    if (element.removeEventListener) {
                        element.removeEventListener(type, handler, false)
                    } else {
                        var key = type + handler.toString();
                        try {
                            element.detachEvent("on" + type, handler._d ? handler._d[key] : handler)
                        } catch (e) {}
                        if (handler._d && handler._d[key]) {
                            var index = utils.indexOf(handler._d.els, element);
                            if (index != -1) {
                                handler._d.els.splice(index, 1)
                            }
                            handler._d.els.length == 0 && delete handler._d[key]
                        }
                    }
                }
            }
        },
        isSameElement: function(nodeA, nodeB) {
            if (nodeA.tagName != nodeB.tagName) {
                return false
            }
            var thisAttrs = nodeA.attributes,
                otherAttrs = nodeB.attributes;
            if (!ie && thisAttrs.length != otherAttrs.length) {
                return false
            }
            var attrA, attrB, al = 0,
                bl = 0;
            for (var i = 0; attrA = thisAttrs[i++];) {
                if (attrA.nodeName == "style") {
                    if (attrA.specified) {
                        al++
                    }
                    if (domUtils.isSameStyle(nodeA, nodeB)) {
                        continue
                    } else {
                        return false
                    }
                }
                if (ie) {
                    if (attrA.specified) {
                        al++;
                        attrB = otherAttrs.getNamedItem(attrA.nodeName)
                    } else {
                        continue
                    }
                } else {
                    attrB = nodeB.attributes[attrA.nodeName]
                }
                if (!attrB.specified || attrA.nodeValue != attrB.nodeValue) {
                    return false
                }
            }
            if (ie) {
                for (i = 0; attrB = otherAttrs[i++];) {
                    if (attrB.specified) {
                        bl++
                    }
                }
                if (al != bl) {
                    return false
                }
            }
            return true
        },
        isSameStyle: function(nodeA, nodeB) {
            var styleA = nodeA.style.cssText.replace(/( ?; ?)/g, ";").replace(/( ?: ?)/g, ":"),
                styleB = nodeB.style.cssText.replace(/( ?; ?)/g, ";").replace(/( ?: ?)/g, ":");
            if (browser.opera) {
                styleA = nodeA.style;
                styleB = nodeB.style;
                if (styleA.length != styleB.length) {
                    return false
                }
                for (var p in styleA) {
                    if (/^(\d+|csstext)$/i.test(p)) {
                        continue
                    }
                    if (styleA[p] != styleB[p]) {
                        return false
                    }
                }
                return true
            }
            if (!styleA || !styleB) {
                return styleA == styleB
            }
            styleA = styleA.split(";");
            styleB = styleB.split(";");
            if (styleA.length != styleB.length) {
                return false
            }
            for (var i = 0, ci; ci = styleA[i++];) {
                if (utils.indexOf(styleB, ci) == -1) {
                    return false
                }
            }
            return true
        },
        isBlockElm: function(node) {
            return node.nodeType == 1 && (dtd.$block[node.tagName] || styleBlock[domUtils.getComputedStyle(node, "display")]) && !dtd.$nonChild[node.tagName]
        },
        isBody: function(node) {
            return node && node.nodeType == 1 && node.tagName.toLowerCase() == "body"
        },
        breakParent: function(node, parent) {
            var tmpNode, parentClone = node,
                clone = node,
                leftNodes, rightNodes;
            do {
                parentClone = parentClone.parentNode;
                if (leftNodes) {
                    tmpNode = parentClone.cloneNode(false);
                    tmpNode.appendChild(leftNodes);
                    leftNodes = tmpNode;
                    tmpNode = parentClone.cloneNode(false);
                    tmpNode.appendChild(rightNodes);
                    rightNodes = tmpNode
                } else {
                    leftNodes = parentClone.cloneNode(false);
                    rightNodes = leftNodes.cloneNode(false)
                }
                while (tmpNode = clone.previousSibling) {
                    leftNodes.insertBefore(tmpNode, leftNodes.firstChild)
                }
                while (tmpNode = clone.nextSibling) {
                    rightNodes.appendChild(tmpNode)
                }
                clone = parentClone
            } while (parent !== parentClone);
            tmpNode = parent.parentNode;
            tmpNode.insertBefore(leftNodes, parent);
            tmpNode.insertBefore(rightNodes, parent);
            tmpNode.insertBefore(node, rightNodes);
            domUtils.remove(parent);
            return node
        },
        isEmptyInlineElement: function(node) {
            if (node.nodeType != 1 || !dtd.$removeEmpty[node.tagName]) {
                return 0
            }
            node = node.firstChild;
            while (node) {
                if (domUtils.isBookmarkNode(node)) {
                    return 0
                }
                if (node.nodeType == 1 && !domUtils.isEmptyInlineElement(node) || node.nodeType == 3 && !domUtils.isWhitespace(node)) {
                    return 0
                }
                node = node.nextSibling
            }
            return 1
        },
        trimWhiteTextNode: function(node) {
            function remove(dir) {
                var child;
                while ((child = node[dir]) && child.nodeType == 3 && domUtils.isWhitespace(child)) {
                    node.removeChild(child)
                }
            }
            remove("firstChild");
            remove("lastChild")
        },
        mergeChild: function(node, tagName, attrs) {
            var list = domUtils.getElementsByTagName(node, node.tagName.toLowerCase());
            for (var i = 0, ci; ci = list[i++];) {
                if (!ci.parentNode || domUtils.isBookmarkNode(ci)) {
                    continue
                }
                if (ci.tagName.toLowerCase() == "span") {
                    if (node === ci.parentNode) {
                        domUtils.trimWhiteTextNode(node);
                        if (node.childNodes.length == 1) {
                            node.style.cssText = ci.style.cssText + ";" + node.style.cssText;
                            domUtils.remove(ci, true);
                            continue
                        }
                    }
                    ci.style.cssText = node.style.cssText + ";" + ci.style.cssText;
                    if (attrs) {
                        var style = attrs.style;
                        if (style) {
                            style = style.split(";");
                            for (var j = 0, s; s = style[j++];) {
                                ci.style[utils.cssStyleToDomStyle(s.split(":")[0])] = s.split(":")[1]
                            }
                        }
                    }
                    if (domUtils.isSameStyle(ci, node)) {
                        domUtils.remove(ci, true)
                    }
                    continue
                }
                if (domUtils.isSameElement(node, ci)) {
                    domUtils.remove(ci, true)
                }
            }
        },
        getElementsByTagName: function(node, name, filter) {
            if (filter && utils.isString(filter)) {
                var className = filter;
                filter = function(node) {
                    return domUtils.hasClass(node, className)
                }
            }
            name = utils.trim(name).replace(/[ ]{2,}/g, " ").split(" ");
            var arr = [];
            for (var n = 0, ni; ni = name[n++];) {
                var list = node.getElementsByTagName(ni);
                for (var i = 0, ci; ci = list[i++];) {
                    if (!filter || filter(ci)) {
                        arr.push(ci)
                    }
                }
            }
            return arr
        },
        mergeToParent: function(node) {
            var parent = node.parentNode;
            while (parent && dtd.$removeEmpty[parent.tagName]) {
                if (parent.tagName == node.tagName || parent.tagName == "A") {
                    domUtils.trimWhiteTextNode(parent);
                    if (parent.tagName == "SPAN" && !domUtils.isSameStyle(parent, node) || (parent.tagName == "A" && node.tagName == "SPAN")) {
                        if (parent.childNodes.length > 1 || parent !== node.parentNode) {
                            node.style.cssText = parent.style.cssText + ";" + node.style.cssText;
                            parent = parent.parentNode;
                            continue
                        } else {
                            parent.style.cssText += ";" + node.style.cssText;
                            if (parent.tagName == "A") {
                                parent.style.textDecoration = "underline"
                            }
                        }
                    }
                    if (parent.tagName != "A") {
                        parent === node.parentNode && domUtils.remove(node, true);
                        break
                    }
                }
                parent = parent.parentNode
            }
        },
        mergeSibling: function(node, ignorePre, ignoreNext) {
            function merge(rtl, start, node) {
                var next;
                if ((next = node[rtl]) && !domUtils.isBookmarkNode(next) && next.nodeType == 1 && domUtils.isSameElement(node, next)) {
                    while (next.firstChild) {
                        if (start == "firstChild") {
                            node.insertBefore(next.lastChild, node.firstChild)
                        } else {
                            node.appendChild(next.firstChild)
                        }
                    }
                    domUtils.remove(next)
                }
            }!ignorePre && merge("previousSibling", "firstChild", node);
            !ignoreNext && merge("nextSibling", "lastChild", node)
        },
        unSelectable: ie && browser.ie9below || browser.opera ?
            function(node) {
                node.onselectstart = function() {
                    return false
                };
                node.onclick = node.onkeyup = node.onkeydown = function() {
                    return false
                };
                node.unselectable = "on";
                node.setAttribute("unselectable", "on");
                for (var i = 0, ci; ci = node.all[i++];) {
                    switch (ci.tagName.toLowerCase()) {
                        case "iframe":
                        case "textarea":
                        case "input":
                        case "select":
                            break;
                        default:
                            ci.unselectable = "on";
                            node.setAttribute("unselectable", "on")
                    }
                }
            } : function(node) {
                node.style.MozUserSelect = node.style.webkitUserSelect = node.style.msUserSelect = node.style.KhtmlUserSelect = "none"
            },
        removeAttributes: function(node, attrNames) {
            attrNames = utils.isArray(attrNames) ? attrNames : utils.trim(attrNames).replace(/[ ]{2,}/g, " ").split(" ");
            for (var i = 0, ci; ci = attrNames[i++];) {
                ci = attrFix[ci] || ci;
                switch (ci) {
                    case "className":
                        node[ci] = "";
                        break;
                    case "style":
                        node.style.cssText = "";
                        var val = node.getAttributeNode("style");
                        !browser.ie && val && node.removeAttributeNode(val)
                }
                node.removeAttribute(ci)
            }
        },
        createElement: function(doc, tag, attrs) {
            return domUtils.setAttributes(doc.createElement(tag), attrs)
        },
        setAttributes: function(node, attrs) {
            for (var attr in attrs) {
                if (attrs.hasOwnProperty(attr)) {
                    var value = attrs[attr];
                    switch (attr) {
                        case "class":
                            node.className = value;
                            break;
                        case "style":
                            node.style.cssText = node.style.cssText + ";" + value;
                            break;
                        case "innerHTML":
                            node[attr] = value;
                            break;
                        case "value":
                            node.value = value;
                            break;
                        default:
                            node.setAttribute(attrFix[attr] || attr, value)
                    }
                }
            }
            return node
        },
        getComputedStyle: function(element, styleName) {
            var pros = "width height top left";
            if (pros.indexOf(styleName) > -1) {
                return element["offset" + styleName.replace(/^\w/, function(s) {
                    return s.toUpperCase()
                })] + "px"
            }
            if (element.nodeType == 3) {
                element = element.parentNode
            }
            if (browser.ie && browser.version < 9 && styleName == "font-size" && !element.style.fontSize && !dtd.$empty[element.tagName] && !dtd.$nonChild[element.tagName]) {
                var span = element.ownerDocument.createElement("span");
                span.style.cssText = "padding:0;border:0;font-family:simsun;";
                span.innerHTML = ".";
                element.appendChild(span);
                var result = span.offsetHeight;
                element.removeChild(span);
                span = null;
                return result + "px"
            }
            try {
                var value = domUtils.getStyle(element, styleName) || (window.getComputedStyle ? domUtils.getWindow(element).getComputedStyle(element, "").getPropertyValue(styleName) : (element.currentStyle || element.style)[utils.cssStyleToDomStyle(styleName)])
            } catch (e) {
                return ""
            }
            return utils.transUnitToPx(utils.fixColor(styleName, value))
        },
        removeClasses: function(elm, classNames) {
            classNames = utils.isArray(classNames) ? classNames : utils.trim(classNames).replace(/[ ]{2,}/g, " ").split(" ");
            for (var i = 0, ci, cls = elm.className; ci = classNames[i++];) {
                cls = cls.replace(new RegExp("\\b" + ci + "\\b"), "")
            }
            cls = utils.trim(cls).replace(/[ ]{2,}/g, " ");
            if (cls) {
                elm.className = cls
            } else {
                domUtils.removeAttributes(elm, ["class"])
            }
        },
        addClass: function(elm, classNames) {
            if (!elm) {
                return
            }
            classNames = utils.trim(classNames).replace(/[ ]{2,}/g, " ").split(" ");
            for (var i = 0, ci, cls = elm.className; ci = classNames[i++];) {
                if (!new RegExp("\\b" + ci + "\\b").test(cls)) {
                    cls += " " + ci
                }
            }
            elm.className = utils.trim(cls)
        },
        hasClass: function(element, className) {
            if (utils.isRegExp(className)) {
                return className.test(element.className)
            }
            className = utils.trim(className).replace(/[ ]{2,}/g, " ").split(" ");
            for (var i = 0, ci, cls = element.className; ci = className[i++];) {
                if (!new RegExp("\\b" + ci + "\\b", "i").test(cls)) {
                    return false
                }
            }
            return i - 1 == className.length
        },
        preventDefault: function(evt) {
            evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false)
        },
        removeStyle: function(element, name) {
            if (browser.ie) {
                if (name == "color") {
                    name = "(^|;)" + name
                }
                element.style.cssText = element.style.cssText.replace(new RegExp(name + "[^:]*:[^;]+;?", "ig"), "")
            } else {
                if (element.style.removeProperty) {
                    element.style.removeProperty(name)
                } else {
                    element.style.removeAttribute(utils.cssStyleToDomStyle(name))
                }
            }
            if (!element.style.cssText) {
                domUtils.removeAttributes(element, ["style"])
            }
        },
        getStyle: function(element, name) {
            var value = element.style[utils.cssStyleToDomStyle(name)];
            return utils.fixColor(name, value)
        },
        setStyle: function(element, name, value) {
            element.style[utils.cssStyleToDomStyle(name)] = value;
            if (!utils.trim(element.style.cssText)) {
                this.removeAttributes(element, "style")
            }
        },
        setStyles: function(element, styles) {
            for (var name in styles) {
                if (styles.hasOwnProperty(name)) {
                    domUtils.setStyle(element, name, styles[name])
                }
            }
        },
        removeDirtyAttr: function(node) {
            for (var i = 0, ci, nodes = node.getElementsByTagName("*"); ci = nodes[i++];) {
                ci.removeAttribute("_moz_dirty")
            }
            node.removeAttribute("_moz_dirty")
        },
        getChildCount: function(node, fn) {
            var count = 0,
                first = node.firstChild;
            fn = fn ||
                function() {
                    return 1
                };
            while (first) {
                if (fn(first)) {
                    count++
                }
                first = first.nextSibling
            }
            return count
        },
        isEmptyNode: function(node) {
            return !node.firstChild || domUtils.getChildCount(node, function(node) {
                return !domUtils.isBr(node) && !domUtils.isBookmarkNode(node) && !domUtils.isWhitespace(node)
            }) == 0
        },
        clearSelectedArr: function(nodes) {
            var node;
            while (node = nodes.pop()) {
                domUtils.removeAttributes(node, ["class"])
            }
        },
        scrollToView: function(node, win, offsetTop) {
            var getViewPaneSize = function() {
                    var doc = win.document,
                        mode = doc.compatMode == "CSS1Compat";
                    return {
                        width: (mode ? doc.documentElement.clientWidth : doc.body.clientWidth) || 0,
                        height: (mode ? doc.documentElement.clientHeight : doc.body.clientHeight) || 0
                    }
                },
                getScrollPosition = function(win) {
                    if ("pageXOffset" in win) {
                        return {
                            x: win.pageXOffset || 0,
                            y: win.pageYOffset || 0
                        }
                    } else {
                        var doc = win.document;
                        return {
                            x: doc.documentElement.scrollLeft || doc.body.scrollLeft || 0,
                            y: doc.documentElement.scrollTop || doc.body.scrollTop || 0
                        }
                    }
                };
            var winHeight = getViewPaneSize().height,
                offset = winHeight * -1 + offsetTop;
            offset += (node.offsetHeight || 0);
            var elementPosition = domUtils.getXY(node);
            offset += elementPosition.y;
            var currentScroll = getScrollPosition(win).y;
            if (offset > currentScroll || offset < currentScroll - winHeight) {
                win.scrollTo(0, offset + (offset < 0 ? -20 : 20))
            }
        },
        isBr: function(node) {
            return node.nodeType == 1 && node.tagName == "BR"
        },
        isFillChar: function(node, isInStart) {
            if (node.nodeType != 3) {
                return false
            }
            var text = node.nodeValue;
            if (isInStart) {
                return new RegExp("^" + domUtils.fillChar).test(text)
            }
            return !text.replace(new RegExp(domUtils.fillChar, "g"), "").length
        },
        isStartInblock: function(range) {
            var tmpRange = range.cloneRange(),
                flag = 0,
                start = tmpRange.startContainer,
                tmp;
            if (start.nodeType == 1 && start.childNodes[tmpRange.startOffset]) {
                start = start.childNodes[tmpRange.startOffset];
                var pre = start.previousSibling;
                while (pre && domUtils.isFillChar(pre)) {
                    start = pre;
                    pre = pre.previousSibling
                }
            }
            if (this.isFillChar(start, true) && tmpRange.startOffset == 1) {
                tmpRange.setStartBefore(start);
                start = tmpRange.startContainer
            }
            while (start && domUtils.isFillChar(start)) {
                tmp = start;
                start = start.previousSibling
            }
            if (tmp) {
                tmpRange.setStartBefore(tmp);
                start = tmpRange.startContainer
            }
            if (start.nodeType == 1 && domUtils.isEmptyNode(start) && tmpRange.startOffset == 1) {
                tmpRange.setStart(start, 0).collapse(true)
            }
            while (!tmpRange.startOffset) {
                start = tmpRange.startContainer;
                if (domUtils.isBlockElm(start) || domUtils.isBody(start)) {
                    flag = 1;
                    break
                }
                var pre = tmpRange.startContainer.previousSibling,
                    tmpNode;
                if (!pre) {
                    tmpRange.setStartBefore(tmpRange.startContainer)
                } else {
                    while (pre && domUtils.isFillChar(pre)) {
                        tmpNode = pre;
                        pre = pre.previousSibling
                    }
                    if (tmpNode) {
                        tmpRange.setStartBefore(tmpNode)
                    } else {
                        tmpRange.setStartBefore(tmpRange.startContainer)
                    }
                }
            }
            return flag && !domUtils.isBody(tmpRange.startContainer) ? 1 : 0
        },
        isEmptyBlock: function(node, reg) {
            if (node.nodeType != 1) {
                return 0
            }
            reg = reg || new RegExp("[  \t\r\n" + domUtils.fillChar + "]", "g");
            if (node[browser.ie ? "innerText" : "textContent"].replace(reg, "").length > 0) {
                return 0
            }
            for (var n in dtd.$isNotEmpty) {
                if (node.getElementsByTagName(n).length) {
                    return 0
                }
            }
            return 1
        },
        setViewportOffset: function(element, offset) {
            var left = parseInt(element.style.left) | 0;
            var top = parseInt(element.style.top) | 0;
            var rect = element.getBoundingClientRect();
            var offsetLeft = offset.left - rect.left;
            var offsetTop = offset.top - rect.top;
            if (offsetLeft) {
                element.style.left = left + offsetLeft + "px"
            }
            if (offsetTop) {
                element.style.top = top + offsetTop + "px"
            }
        },
        fillNode: function(doc, node) {
            var tmpNode = browser.ie ? doc.createTextNode(domUtils.fillChar) : doc.createElement("br");
            node.innerHTML = "";
            node.appendChild(tmpNode)
        },
        moveChild: function(src, tag, dir) {
            while (src.firstChild) {
                if (dir && tag.firstChild) {
                    tag.insertBefore(src.lastChild, tag.firstChild)
                } else {
                    tag.appendChild(src.firstChild)
                }
            }
        },
        hasNoAttributes: function(node) {
            return browser.ie ? /^<\w+\s*?>/.test(node.outerHTML) : node.attributes.length == 0
        },
        isCustomeNode: function(node) {
            return node.nodeType == 1 && node.getAttribute("_ue_custom_node_")
        },
        isTagNode: function(node, tagNames) {
            return node.nodeType == 1 && new RegExp("\\b" + node.tagName + "\\b", "i").test(tagNames)
        },
        filterNodeList: function(nodelist, filter, forAll) {
            var results = [];
            if (!utils.isFunction(filter)) {
                var str = filter;
                filter = function(n) {
                    return utils.indexOf(utils.isArray(str) ? str : str.split(" "), n.tagName.toLowerCase()) != -1
                }
            }
            utils.each(nodelist, function(n) {
                filter(n) && results.push(n)
            });
            return results.length == 0 ? null : results.length == 1 || !forAll ? results[0] : results
        },
        isInNodeEndBoundary: function(rng, node) {
            var start = rng.startContainer;
            if (start.nodeType == 3 && rng.startOffset != start.nodeValue.length) {
                return 0
            }
            if (start.nodeType == 1 && rng.startOffset != start.childNodes.length) {
                return 0
            }
            while (start !== node) {
                if (start.nextSibling) {
                    return 0
                }
                start = start.parentNode
            }
            return 1
        },
        isBoundaryNode: function(node, dir) {
            var tmp;
            while (!domUtils.isBody(node)) {
                tmp = node;
                node = node.parentNode;
                if (tmp !== node[dir]) {
                    return false
                }
            }
            return true
        },
        fillHtml: browser.ie11below ? "&nbsp;" : "<br/>"
    };
    var fillCharReg = new RegExp(domUtils.fillChar, "g");
    (function() {
        var guid = 0,
            fillChar = domUtils.fillChar,
            fillData;

        function updateCollapse(range) {
            range.collapsed = range.startContainer && range.endContainer && range.startContainer === range.endContainer && range.startOffset == range.endOffset
        }
        function selectOneNode(rng) {
            return !rng.collapsed && rng.startContainer.nodeType == 1 && rng.startContainer === rng.endContainer && rng.endOffset - rng.startOffset == 1
        }
        function setEndPoint(toStart, node, offset, range) {
            if (node.nodeType == 1 && (dtd.$empty[node.tagName] || dtd.$nonChild[node.tagName])) {
                offset = domUtils.getNodeIndex(node) + (toStart ? 0 : 1);
                node = node.parentNode
            }
            if (toStart) {
                range.startContainer = node;
                range.startOffset = offset;
                if (!range.endContainer) {
                    range.collapse(true)
                }
            } else {
                range.endContainer = node;
                range.endOffset = offset;
                if (!range.startContainer) {
                    range.collapse(false)
                }
            }
            updateCollapse(range);
            return range
        }
        function execContentsAction(range, action) {
            var start = range.startContainer,
                end = range.endContainer,
                startOffset = range.startOffset,
                endOffset = range.endOffset,
                doc = range.document,
                frag = doc.createDocumentFragment(),
                tmpStart, tmpEnd;
            if (start.nodeType == 1) {
                start = start.childNodes[startOffset] || (tmpStart = start.appendChild(doc.createTextNode("")))
            }
            if (end.nodeType == 1) {
                end = end.childNodes[endOffset] || (tmpEnd = end.appendChild(doc.createTextNode("")))
            }
            if (start === end && start.nodeType == 3) {
                frag.appendChild(doc.createTextNode(start.substringData(startOffset, endOffset - startOffset)));
                if (action) {
                    start.deleteData(startOffset, endOffset - startOffset);
                    range.collapse(true)
                }
                return frag
            }
            var current, currentLevel, clone = frag,
                startParents = domUtils.findParents(start, true),
                endParents = domUtils.findParents(end, true);
            for (var i = 0; startParents[i] == endParents[i];) {
                i++
            }
            for (var j = i, si; si = startParents[j]; j++) {
                current = si.nextSibling;
                if (si == start) {
                    if (!tmpStart) {
                        if (range.startContainer.nodeType == 3) {
                            clone.appendChild(doc.createTextNode(start.nodeValue.slice(startOffset)));
                            if (action) {
                                start.deleteData(startOffset, start.nodeValue.length - startOffset)
                            }
                        } else {
                            clone.appendChild(!action ? start.cloneNode(true) : start)
                        }
                    }
                } else {
                    currentLevel = si.cloneNode(false);
                    clone.appendChild(currentLevel)
                }
                while (current) {
                    if (current === end || current === endParents[j]) {
                        break
                    }
                    si = current.nextSibling;
                    clone.appendChild(!action ? current.cloneNode(true) : current);
                    current = si
                }
                clone = currentLevel
            }
            clone = frag;
            if (!startParents[i]) {
                clone.appendChild(startParents[i - 1].cloneNode(false));
                clone = clone.firstChild
            }
            for (var j = i, ei;
                 ei = endParents[j]; j++) {
                current = ei.previousSibling;
                if (ei == end) {
                    if (!tmpEnd && range.endContainer.nodeType == 3) {
                        clone.appendChild(doc.createTextNode(end.substringData(0, endOffset)));
                        if (action) {
                            end.deleteData(0, endOffset)
                        }
                    }
                } else {
                    currentLevel = ei.cloneNode(false);
                    clone.appendChild(currentLevel)
                }
                if (j != i || !startParents[i]) {
                    while (current) {
                        if (current === start) {
                            break
                        }
                        ei = current.previousSibling;
                        clone.insertBefore(!action ? current.cloneNode(true) : current, clone.firstChild);
                        current = ei
                    }
                }
                clone = currentLevel
            }
            if (action) {
                range.setStartBefore(!endParents[i] ? endParents[i - 1] : !startParents[i] ? startParents[i - 1] : endParents[i]).collapse(true)
            }
            tmpStart && domUtils.remove(tmpStart);
            tmpEnd && domUtils.remove(tmpEnd);
            return frag
        }
        var Range = dom.Range = function(document) {
            var me = this;
            me.startContainer = me.startOffset = me.endContainer = me.endOffset = null;
            me.document = document;
            me.collapsed = true
        };

        function removeFillData(doc, excludeNode) {
            try {
                if (fillData && domUtils.inDoc(fillData, doc)) {
                    if (!fillData.nodeValue.replace(fillCharReg, "").length) {
                        var tmpNode = fillData.parentNode;
                        domUtils.remove(fillData);
                        while (tmpNode && domUtils.isEmptyInlineElement(tmpNode) && (browser.safari ? !(domUtils.getPosition(tmpNode, excludeNode) & domUtils.POSITION_CONTAINS) : !tmpNode.contains(excludeNode))) {
                            fillData = tmpNode.parentNode;
                            domUtils.remove(tmpNode);
                            tmpNode = fillData
                        }
                    } else {
                        fillData.nodeValue = fillData.nodeValue.replace(fillCharReg, "")
                    }
                }
            } catch (e) {}
        }
        function mergeSibling(node, dir) {
            var tmpNode;
            node = node[dir];
            while (node && domUtils.isFillChar(node)) {
                tmpNode = node[dir];
                domUtils.remove(node);
                node = tmpNode
            }
        }
        Range.prototype = {
            cloneContents: function() {
                return this.collapsed ? null : execContentsAction(this, 0)
            },
            deleteContents: function() {
                var txt;
                if (!this.collapsed) {
                    execContentsAction(this, 1)
                }
                if (browser.webkit) {
                    txt = this.startContainer;
                    if (txt.nodeType == 3 && !txt.nodeValue.length) {
                        this.setStartBefore(txt).collapse(true);
                        domUtils.remove(txt)
                    }
                }
                return this
            },
            extractContents: function() {
                return this.collapsed ? null : execContentsAction(this, 2)
            },
            setStart: function(node, offset) {
                return setEndPoint(true, node, offset, this)
            },
            setEnd: function(node, offset) {
                return setEndPoint(false, node, offset, this)
            },
            setStartAfter: function(node) {
                return this.setStart(node.parentNode, domUtils.getNodeIndex(node) + 1)
            },
            setStartBefore: function(node) {
                return this.setStart(node.parentNode, domUtils.getNodeIndex(node))
            },
            setEndAfter: function(node) {
                return this.setEnd(node.parentNode, domUtils.getNodeIndex(node) + 1)
            },
            setEndBefore: function(node) {
                return this.setEnd(node.parentNode, domUtils.getNodeIndex(node))
            },
            setStartAtFirst: function(node) {
                return this.setStart(node, 0)
            },
            setStartAtLast: function(node) {
                return this.setStart(node, node.nodeType == 3 ? node.nodeValue.length : node.childNodes.length)
            },
            setEndAtFirst: function(node) {
                return this.setEnd(node, 0)
            },
            setEndAtLast: function(node) {
                return this.setEnd(node, node.nodeType == 3 ? node.nodeValue.length : node.childNodes.length)
            },
            selectNode: function(node) {
                return this.setStartBefore(node).setEndAfter(node)
            },
            selectNodeContents: function(node) {
                return this.setStart(node, 0).setEndAtLast(node)
            },
            cloneRange: function() {
                var me = this;
                return new Range(me.document).setStart(me.startContainer, me.startOffset).setEnd(me.endContainer, me.endOffset)
            },
            collapse: function(toStart) {
                var me = this;
                if (toStart) {
                    me.endContainer = me.startContainer;
                    me.endOffset = me.startOffset
                } else {
                    me.startContainer = me.endContainer;
                    me.startOffset = me.endOffset
                }
                me.collapsed = true;
                return me
            },
            shrinkBoundary: function(ignoreEnd) {
                var me = this,
                    child, collapsed = me.collapsed;

                function check(node) {
                    return node.nodeType == 1 && !domUtils.isBookmarkNode(node) && !dtd.$empty[node.tagName] && !dtd.$nonChild[node.tagName]
                }
                while (me.startContainer.nodeType == 1 && (child = me.startContainer.childNodes[me.startOffset]) && check(child)) {
                    me.setStart(child, 0)
                }
                if (collapsed) {
                    return me.collapse(true)
                }
                if (!ignoreEnd) {
                    while (me.endContainer.nodeType == 1 && me.endOffset > 0 && (child = me.endContainer.childNodes[me.endOffset - 1]) && check(child)) {
                        me.setEnd(child, child.childNodes.length)
                    }
                }
                return me
            },
            getCommonAncestor: function(includeSelf, ignoreTextNode) {
                var me = this,
                    start = me.startContainer,
                    end = me.endContainer;
                if (start === end) {
                    if (includeSelf && selectOneNode(this)) {
                        start = start.childNodes[me.startOffset];
                        if (start.nodeType == 1) {
                            return start
                        }
                    }
                    return ignoreTextNode && start.nodeType == 3 ? start.parentNode : start
                }
                return domUtils.getCommonAncestor(start, end)
            },
            trimBoundary: function(ignoreEnd) {
                this.txtToElmBoundary();
                var start = this.startContainer,
                    offset = this.startOffset,
                    collapsed = this.collapsed,
                    end = this.endContainer;
                if (start.nodeType == 3) {
                    if (offset == 0) {
                        this.setStartBefore(start)
                    } else {
                        if (offset >= start.nodeValue.length) {
                            this.setStartAfter(start)
                        } else {
                            var textNode = domUtils.split(start, offset);
                            if (start === end) {
                                this.setEnd(textNode, this.endOffset - offset)
                            } else {
                                if (start.parentNode === end) {
                                    this.endOffset += 1
                                }
                            }
                            this.setStartBefore(textNode)
                        }
                    }
                    if (collapsed) {
                        return this.collapse(true)
                    }
                }
                if (!ignoreEnd) {
                    offset = this.endOffset;
                    end = this.endContainer;
                    if (end.nodeType == 3) {
                        if (offset == 0) {
                            this.setEndBefore(end)
                        } else {
                            offset < end.nodeValue.length && domUtils.split(end, offset);
                            this.setEndAfter(end)
                        }
                    }
                }
                return this
            },
            txtToElmBoundary: function(ignoreCollapsed) {
                function adjust(r, c) {
                    var container = r[c + "Container"],
                        offset = r[c + "Offset"];
                    if (container.nodeType == 3) {
                        if (!offset) {
                            r["set" + c.replace(/(\w)/, function(a) {
                                return a.toUpperCase()
                            }) + "Before"](container)
                        } else {
                            if (offset >= container.nodeValue.length) {
                                r["set" + c.replace(/(\w)/, function(a) {
                                    return a.toUpperCase()
                                }) + "After"](container)
                            }
                        }
                    }
                }
                if (ignoreCollapsed || !this.collapsed) {
                    adjust(this, "start");
                    adjust(this, "end")
                }
                return this
            },
            insertNode: function(node) {
                var first = node,
                    length = 1;
                if (node.nodeType == 11) {
                    first = node.firstChild;
                    length = node.childNodes.length
                }
                this.trimBoundary(true);
                var start = this.startContainer,
                    offset = this.startOffset;
                var nextNode = start.childNodes[offset];
                if (nextNode) {
                    start.insertBefore(node, nextNode)
                } else {
                    start.appendChild(node)
                }
                if (first.parentNode === this.endContainer) {
                    this.endOffset = this.endOffset + length
                }
                return this.setStartBefore(first)
            },
            setCursor: function(toEnd, noFillData) {
                return this.collapse(!toEnd).select(noFillData)
            },
            createBookmark: function(serialize, same) {
                var endNode, startNode = this.document.createElement("span");
                startNode.style.cssText = "display:none;line-height:0px;";
                startNode.appendChild(this.document.createTextNode("‍"));
                startNode.id = "_baidu_bookmark_start_" + (same ? "" : guid++);
                if (!this.collapsed) {
                    endNode = startNode.cloneNode(true);
                    endNode.id = "_baidu_bookmark_end_" + (same ? "" : guid++)
                }
                this.insertNode(startNode);
                if (endNode) {
                    this.collapse().insertNode(endNode).setEndBefore(endNode)
                }
                this.setStartAfter(startNode);
                return {
                    start: serialize ? startNode.id : startNode,
                    end: endNode ? serialize ? endNode.id : endNode : null,
                    id: serialize
                }
            },
            moveToBookmark: function(bookmark) {
                var start = bookmark.id ? this.document.getElementById(bookmark.start) : bookmark.start,
                    end = bookmark.end && bookmark.id ? this.document.getElementById(bookmark.end) : bookmark.end;
                this.setStartBefore(start);
                domUtils.remove(start);
                if (end) {
                    this.setEndBefore(end);
                    domUtils.remove(end)
                } else {
                    this.collapse(true)
                }
                return this
            },
            enlarge: function(toBlock, stopFn) {
                var isBody = domUtils.isBody,
                    pre, node, tmp = this.document.createTextNode("");
                if (toBlock) {
                    node = this.startContainer;
                    if (node.nodeType == 1) {
                        if (node.childNodes[this.startOffset]) {
                            pre = node = node.childNodes[this.startOffset]
                        } else {
                            node.appendChild(tmp);
                            pre = node = tmp
                        }
                    } else {
                        pre = node
                    }
                    while (1) {
                        if (domUtils.isBlockElm(node)) {
                            node = pre;
                            while ((pre = node.previousSibling) && !domUtils.isBlockElm(pre)) {
                                node = pre
                            }
                            this.setStartBefore(node);
                            break
                        }
                        pre = node;
                        node = node.parentNode
                    }
                    node = this.endContainer;
                    if (node.nodeType == 1) {
                        if (pre = node.childNodes[this.endOffset]) {
                            node.insertBefore(tmp, pre)
                        } else {
                            node.appendChild(tmp)
                        }
                        pre = node = tmp
                    } else {
                        pre = node
                    }
                    while (1) {
                        if (domUtils.isBlockElm(node)) {
                            node = pre;
                            while ((pre = node.nextSibling) && !domUtils.isBlockElm(pre)) {
                                node = pre
                            }
                            this.setEndAfter(node);
                            break
                        }
                        pre = node;
                        node = node.parentNode
                    }
                    if (tmp.parentNode === this.endContainer) {
                        this.endOffset--
                    }
                    domUtils.remove(tmp)
                }
                if (!this.collapsed) {
                    while (this.startOffset == 0) {
                        if (stopFn && stopFn(this.startContainer)) {
                            break
                        }
                        if (isBody(this.startContainer)) {
                            break
                        }
                        this.setStartBefore(this.startContainer)
                    }
                    while (this.endOffset == (this.endContainer.nodeType == 1 ? this.endContainer.childNodes.length : this.endContainer.nodeValue.length)) {
                        if (stopFn && stopFn(this.endContainer)) {
                            break
                        }
                        if (isBody(this.endContainer)) {
                            break
                        }
                        this.setEndAfter(this.endContainer)
                    }
                }
                return this
            },
            enlargeToBlockElm: function(ignoreEnd) {
                while (!domUtils.isBlockElm(this.startContainer)) {
                    this.setStartBefore(this.startContainer)
                }
                if (!ignoreEnd) {
                    while (!domUtils.isBlockElm(this.endContainer)) {
                        this.setEndAfter(this.endContainer)
                    }
                }
                return this
            },
            adjustmentBoundary: function() {
                if (!this.collapsed) {
                    while (!domUtils.isBody(this.startContainer) && this.startOffset == this.startContainer[this.startContainer.nodeType == 3 ? "nodeValue" : "childNodes"].length && this.startContainer[this.startContainer.nodeType == 3 ? "nodeValue" : "childNodes"].length) {
                        this.setStartAfter(this.startContainer)
                    }
                    while (!domUtils.isBody(this.endContainer) && !this.endOffset && this.endContainer[this.endContainer.nodeType == 3 ? "nodeValue" : "childNodes"].length) {
                        this.setEndBefore(this.endContainer)
                    }
                }
                return this
            },
            applyInlineStyle: function(tagName, attrs, list) {
                if (this.collapsed) {
                    return this
                }
                this.trimBoundary().enlarge(false, function(node) {
                    return node.nodeType == 1 && domUtils.isBlockElm(node)
                }).adjustmentBoundary();
                var bookmark = this.createBookmark(),
                    end = bookmark.end,
                    filterFn = function(node) {
                        return node.nodeType == 1 ? node.tagName.toLowerCase() != "br" : !domUtils.isWhitespace(node)
                    },
                    current = domUtils.getNextDomNode(bookmark.start, false, filterFn),
                    node, pre, range = this.cloneRange();
                while (current && (domUtils.getPosition(current, end) & domUtils.POSITION_PRECEDING)) {
                    if (current.nodeType == 3 || dtd[tagName][current.tagName]) {
                        range.setStartBefore(current);
                        node = current;
                        while (node && (node.nodeType == 3 || dtd[tagName][node.tagName]) && node !== end) {
                            pre = node;
                            node = domUtils.getNextDomNode(node, node.nodeType == 1, null, function(parent) {
                                return dtd[tagName][parent.tagName]
                            })
                        }
                        var frag = range.setEndAfter(pre).extractContents(),
                            elm;
                        if (list && list.length > 0) {
                            var level, top;
                            top = level = list[0].cloneNode(false);
                            for (var i = 1, ci; ci = list[i++];) {
                                level.appendChild(ci.cloneNode(false));
                                level = level.firstChild
                            }
                            elm = level
                        } else {
                            elm = range.document.createElement(tagName)
                        }
                        if (attrs) {
                            domUtils.setAttributes(elm, attrs)
                        }
                        elm.appendChild(frag);
                        range.insertNode(list ? top : elm);
                        var aNode;
                        if (tagName == "span" && attrs.style && /text\-decoration/.test(attrs.style) && (aNode = domUtils.findParentByTagName(elm, "a", true))) {
                            domUtils.setAttributes(aNode, attrs);
                            domUtils.remove(elm, true);
                            elm = aNode
                        } else {
                            domUtils.mergeSibling(elm);
                            domUtils.clearEmptySibling(elm)
                        }
                        domUtils.mergeChild(elm, attrs);
                        current = domUtils.getNextDomNode(elm, false, filterFn);
                        domUtils.mergeToParent(elm);
                        if (node === end) {
                            break
                        }
                    } else {
                        current = domUtils.getNextDomNode(current, true, filterFn)
                    }
                }
                return this.moveToBookmark(bookmark)
            },
            removeInlineStyle: function(tagNames) {
                if (this.collapsed) {
                    return this
                }
                tagNames = utils.isArray(tagNames) ? tagNames : [tagNames];
                this.shrinkBoundary().adjustmentBoundary();
                var start = this.startContainer,
                    end = this.endContainer;
                while (1) {
                    if (start.nodeType == 1) {
                        if (utils.indexOf(tagNames, start.tagName.toLowerCase()) > -1) {
                            break
                        }
                        if (start.tagName.toLowerCase() == "body") {
                            start = null;
                            break
                        }
                    }
                    start = start.parentNode
                }
                while (1) {
                    if (end.nodeType == 1) {
                        if (utils.indexOf(tagNames, end.tagName.toLowerCase()) > -1) {
                            break
                        }
                        if (end.tagName.toLowerCase() == "body") {
                            end = null;
                            break
                        }
                    }
                    end = end.parentNode
                }
                var bookmark = this.createBookmark(),
                    frag, tmpRange;
                if (start) {
                    tmpRange = this.cloneRange().setEndBefore(bookmark.start).setStartBefore(start);
                    frag = tmpRange.extractContents();
                    tmpRange.insertNode(frag);
                    domUtils.clearEmptySibling(start, true);
                    start.parentNode.insertBefore(bookmark.start, start)
                }
                if (end) {
                    tmpRange = this.cloneRange().setStartAfter(bookmark.end).setEndAfter(end);
                    frag = tmpRange.extractContents();
                    tmpRange.insertNode(frag);
                    domUtils.clearEmptySibling(end, false, true);
                    end.parentNode.insertBefore(bookmark.end, end.nextSibling)
                }
                var current = domUtils.getNextDomNode(bookmark.start, false, function(node) {
                        return node.nodeType == 1
                    }),
                    next;
                while (current && current !== bookmark.end) {
                    next = domUtils.getNextDomNode(current, true, function(node) {
                        return node.nodeType == 1
                    });
                    if (utils.indexOf(tagNames, current.tagName.toLowerCase()) > -1) {
                        domUtils.remove(current, true)
                    }
                    current = next
                }
                return this.moveToBookmark(bookmark)
            },
            getClosedNode: function() {
                var node;
                if (!this.collapsed) {
                    var range = this.cloneRange().adjustmentBoundary().shrinkBoundary();
                    if (selectOneNode(range)) {
                        var child = range.startContainer.childNodes[range.startOffset];
                        if (child && child.nodeType == 1 && (dtd.$empty[child.tagName] || dtd.$nonChild[child.tagName])) {
                            node = child
                        }
                    }
                }
                return node
            },
            select: browser.ie ?
                function(noFillData, textRange) {
                    var nativeRange;
                    if (!this.collapsed) {
                        this.shrinkBoundary()
                    }
                    var node = this.getClosedNode();
                    if (node && !textRange) {
                        try {
                            nativeRange = this.document.body.createControlRange();
                            nativeRange.addElement(node);
                            nativeRange.select()
                        } catch (e) {}
                        return this
                    }
                    var bookmark = this.createBookmark(),
                        start = bookmark.start,
                        end;
                    nativeRange = this.document.body.createTextRange();
                    nativeRange.moveToElementText(start);
                    nativeRange.moveStart("character", 1);
                    if (!this.collapsed) {
                        var nativeRangeEnd = this.document.body.createTextRange();
                        end = bookmark.end;
                        nativeRangeEnd.moveToElementText(end);
                        nativeRange.setEndPoint("EndToEnd", nativeRangeEnd)
                    } else {
                        if (!noFillData && this.startContainer.nodeType != 3) {
                            var tmpText = this.document.createTextNode(fillChar),
                                tmp = this.document.createElement("span");
                            tmp.appendChild(this.document.createTextNode(fillChar));
                            start.parentNode.insertBefore(tmp, start);
                            start.parentNode.insertBefore(tmpText, start);
                            removeFillData(this.document, tmpText);
                            fillData = tmpText;
                            mergeSibling(tmp, "previousSibling");
                            mergeSibling(start, "nextSibling");
                            nativeRange.moveStart("character", -1);
                            nativeRange.collapse(true)
                        }
                    }
                    this.moveToBookmark(bookmark);
                    tmp && domUtils.remove(tmp);
                    try {
                        nativeRange.select()
                    } catch (e) {}
                    return this
                } : function(notInsertFillData) {
                    function checkOffset(rng) {
                        function check(node, offset, dir) {
                            if (node.nodeType == 3 && node.nodeValue.length < offset) {
                                rng[dir + "Offset"] = node.nodeValue.length
                            }
                        }
                        check(rng.startContainer, rng.startOffset, "start");
                        check(rng.endContainer, rng.endOffset, "end")
                    }
                    var win = domUtils.getWindow(this.document),
                        sel = win.getSelection(),
                        txtNode;
                    browser.gecko ? this.document.body.focus() : win.focus();
                    if (sel) {
                        sel.removeAllRanges();
                        if (this.collapsed && !notInsertFillData) {
                            var start = this.startContainer,
                                child = start;
                            if (start.nodeType == 1) {
                                child = start.childNodes[this.startOffset]
                            }
                            if (!(start.nodeType == 3 && this.startOffset) && (child ? (!child.previousSibling || child.previousSibling.nodeType != 3) : (!start.lastChild || start.lastChild.nodeType != 3))) {
                                txtNode = this.document.createTextNode(fillChar);
                                this.insertNode(txtNode);
                                removeFillData(this.document, txtNode);
                                mergeSibling(txtNode, "previousSibling");
                                mergeSibling(txtNode, "nextSibling");
                                fillData = txtNode;
                                this.setStart(txtNode, browser.webkit ? 1 : 0).collapse(true)
                            }
                        }
                        var nativeRange = this.document.createRange();
                        if (this.collapsed && browser.opera && this.startContainer.nodeType == 1) {
                            var child = this.startContainer.childNodes[this.startOffset];
                            if (!child) {
                                child = this.startContainer.lastChild;
                                if (child && domUtils.isBr(child)) {
                                    this.setStartBefore(child).collapse(true)
                                }
                            } else {
                                while (child && domUtils.isBlockElm(child)) {
                                    if (child.nodeType == 1 && child.childNodes[0]) {
                                        child = child.childNodes[0]
                                    } else {
                                        break
                                    }
                                }
                                child && this.setStartBefore(child).collapse(true)
                            }
                        }
                        checkOffset(this);
                        nativeRange.setStart(this.startContainer, this.startOffset);
                        nativeRange.setEnd(this.endContainer, this.endOffset);
                        sel.addRange(nativeRange)
                    }
                    return this
                },
            scrollToView: function(win, offset) {
                win = win ? window : domUtils.getWindow(this.document);
                var me = this,
                    span = me.document.createElement("span");
                span.innerHTML = "&nbsp;";
                me.cloneRange().insertNode(span);
                domUtils.scrollToView(span, win, offset);
                domUtils.remove(span);
                return me
            },
            inFillChar: function() {
                var start = this.startContainer;
                if (this.collapsed && start.nodeType == 3 && start.nodeValue.replace(new RegExp("^" + domUtils.fillChar), "").length + 1 == start.nodeValue.length) {
                    return true
                }
                return false
            },
            createAddress: function(ignoreEnd, ignoreTxt) {
                var addr = {},
                    me = this;

                function getAddress(isStart) {
                    var node = isStart ? me.startContainer : me.endContainer;
                    var parents = domUtils.findParents(node, true, function(node) {
                            return !domUtils.isBody(node)
                        }),
                        addrs = [];
                    for (var i = 0, ci; ci = parents[i++];) {
                        addrs.push(domUtils.getNodeIndex(ci, ignoreTxt))
                    }
                    var firstIndex = 0;
                    if (ignoreTxt) {
                        if (node.nodeType == 3) {
                            var tmpNode = node.previousSibling;
                            while (tmpNode && tmpNode.nodeType == 3) {
                                firstIndex += tmpNode.nodeValue.replace(fillCharReg, "").length;
                                tmpNode = tmpNode.previousSibling
                            }
                            firstIndex += (isStart ? me.startOffset : me.endOffset)
                        } else {
                            node = node.childNodes[isStart ? me.startOffset : me.endOffset];
                            if (node) {
                                firstIndex = domUtils.getNodeIndex(node, ignoreTxt)
                            } else {
                                node = isStart ? me.startContainer : me.endContainer;
                                var first = node.firstChild;
                                while (first) {
                                    if (domUtils.isFillChar(first)) {
                                        first = first.nextSibling;
                                        continue
                                    }
                                    firstIndex++;
                                    if (first.nodeType == 3) {
                                        while (first && first.nodeType == 3) {
                                            first = first.nextSibling
                                        }
                                    } else {
                                        first = first.nextSibling
                                    }
                                }
                            }
                        }
                    } else {
                        firstIndex = isStart ? domUtils.isFillChar(node) ? 0 : me.startOffset : me.endOffset
                    }
                    if (firstIndex < 0) {
                        firstIndex = 0
                    }
                    addrs.push(firstIndex);
                    return addrs
                }
                addr.startAddress = getAddress(true);
                if (!ignoreEnd) {
                    addr.endAddress = me.collapsed ? [].concat(addr.startAddress) : getAddress()
                }
                return addr
            },
            moveToAddress: function(addr, ignoreEnd) {
                var me = this;

                function getNode(address, isStart) {
                    var tmpNode = me.document.body,
                        parentNode, offset;
                    for (var i = 0, ci, l = address.length; i < l; i++) {
                        ci = address[i];
                        parentNode = tmpNode;
                        tmpNode = tmpNode.childNodes[ci];
                        if (!tmpNode) {
                            offset = ci;
                            break
                        }
                    }
                    if (isStart) {
                        if (tmpNode) {
                            me.setStartBefore(tmpNode)
                        } else {
                            me.setStart(parentNode, offset)
                        }
                    } else {
                        if (tmpNode) {
                            me.setEndBefore(tmpNode)
                        } else {
                            me.setEnd(parentNode, offset)
                        }
                    }
                }
                getNode(addr.startAddress, true);
                !ignoreEnd && addr.endAddress && getNode(addr.endAddress);
                return me
            },
            equals: function(rng) {
                for (var p in this) {
                    if (this.hasOwnProperty(p)) {
                        if (this[p] !== rng[p]) {
                            return false
                        }
                    }
                }
                return true
            },
            traversal: function(doFn, filterFn) {
                if (this.collapsed) {
                    return this
                }
                var bookmark = this.createBookmark(),
                    end = bookmark.end,
                    current = domUtils.getNextDomNode(bookmark.start, false, filterFn);
                while (current && current !== end && (domUtils.getPosition(current, end) & domUtils.POSITION_PRECEDING)) {
                    var tmpNode = domUtils.getNextDomNode(current, false, filterFn);
                    doFn(current);
                    current = tmpNode
                }
                return this.moveToBookmark(bookmark)
            }
        }
    })();
    (function() {
        function getBoundaryInformation(range, start) {
            var getIndex = domUtils.getNodeIndex;
            range = range.duplicate();
            range.collapse(start);
            var parent = range.parentElement();
            if (!parent.hasChildNodes()) {
                return {
                    container: parent,
                    offset: 0
                }
            }
            var siblings = parent.children,
                child, testRange = range.duplicate(),
                startIndex = 0,
                endIndex = siblings.length - 1,
                index = -1,
                distance;
            while (startIndex <= endIndex) {
                index = Math.floor((startIndex + endIndex) / 2);
                child = siblings[index];
                testRange.moveToElementText(child);
                var position = testRange.compareEndPoints("StartToStart", range);
                if (position > 0) {
                    endIndex = index - 1
                } else {
                    if (position < 0) {
                        startIndex = index + 1
                    } else {
                        return {
                            container: parent,
                            offset: getIndex(child)
                        }
                    }
                }
            }
            if (index == -1) {
                testRange.moveToElementText(parent);
                testRange.setEndPoint("StartToStart", range);
                distance = testRange.text.replace(/(\r\n|\r)/g, "\n").length;
                siblings = parent.childNodes;
                if (!distance) {
                    child = siblings[siblings.length - 1];
                    return {
                        container: child,
                        offset: child.nodeValue.length
                    }
                }
                var i = siblings.length;
                while (distance > 0) {
                    distance -= siblings[--i].nodeValue.length
                }
                return {
                    container: siblings[i],
                    offset: -distance
                }
            }
            testRange.collapse(position > 0);
            testRange.setEndPoint(position > 0 ? "StartToStart" : "EndToStart", range);
            distance = testRange.text.replace(/(\r\n|\r)/g, "\n").length;
            if (!distance) {
                return dtd.$empty[child.tagName] || dtd.$nonChild[child.tagName] ? {
                    container: parent,
                    offset: getIndex(child) + (position > 0 ? 0 : 1)
                } : {
                    container: child,
                    offset: position > 0 ? 0 : child.childNodes.length
                }
            }
            while (distance > 0) {
                try {
                    var pre = child;
                    child = child[position > 0 ? "previousSibling" : "nextSibling"];
                    distance -= child.nodeValue.length
                } catch (e) {
                    return {
                        container: parent,
                        offset: getIndex(pre)
                    }
                }
            }
            return {
                container: child,
                offset: position > 0 ? -distance : child.nodeValue.length + distance
            }
        }
        function transformIERangeToRange(ieRange, range) {
            if (ieRange.item) {
                range.selectNode(ieRange.item(0))
            } else {
                var bi = getBoundaryInformation(ieRange, true);
                range.setStart(bi.container, bi.offset);
                if (ieRange.compareEndPoints("StartToEnd", ieRange) != 0) {
                    bi = getBoundaryInformation(ieRange, false);
                    range.setEnd(bi.container, bi.offset)
                }
            }
            return range
        }
        function _getIERange(sel) {
            var ieRange;
            try {
                ieRange = sel.getNative().createRange()
            } catch (e) {
                return null
            }
            var el = ieRange.item ? ieRange.item(0) : ieRange.parentElement();
            if ((el.ownerDocument || el) === sel.document) {
                return ieRange
            }
            return null
        }
        var Selection = dom.Selection = function(doc) {
            var me = this,
                iframe;
            me.document = doc;
            if (browser.ie9below) {
                iframe = domUtils.getWindow(doc).frameElement;
                domUtils.on(iframe, "beforedeactivate", function() {
                    me._bakIERange = me.getIERange()
                });
                domUtils.on(iframe, "activate", function() {
                    try {
                        if (!_getIERange(me) && me._bakIERange) {
                            me._bakIERange.select()
                        }
                    } catch (ex) {}
                    me._bakIERange = null
                })
            }
            iframe = doc = null
        };
        Selection.prototype = {
            rangeInBody: function(rng, txtRange) {
                var node = browser.ie9below || txtRange ? rng.item ? rng.item() : rng.parentElement() : rng.startContainer;
                return node === this.document.body || domUtils.inDoc(node, this.document)
            },
            getNative: function() {
                var doc = this.document;
                try {
                    return !doc ? null : browser.ie9below ? doc.selection : domUtils.getWindow(doc).getSelection()
                } catch (e) {
                    return null
                }
            },
            getIERange: function() {
                var ieRange = _getIERange(this);
                if (!ieRange) {
                    if (this._bakIERange) {
                        return this._bakIERange
                    }
                }
                return ieRange
            },
            cache: function() {
                this.clear();
                this._cachedRange = this.getRange();
                this._cachedStartElement = this.getStart();
                this._cachedStartElementPath = this.getStartElementPath()
            },
            getStartElementPath: function() {
                if (this._cachedStartElementPath) {
                    return this._cachedStartElementPath
                }
                var start = this.getStart();
                if (start) {
                    return domUtils.findParents(start, true, null, true)
                }
                return []
            },
            clear: function() {
                this._cachedStartElementPath = this._cachedRange = this._cachedStartElement = null
            },
            isFocus: function() {
                try {
                    if (browser.ie9below) {
                        var nativeRange = _getIERange(this);
                        return !!(nativeRange && this.rangeInBody(nativeRange))
                    } else {
                        return !!this.getNative().rangeCount
                    }
                } catch (e) {
                    return false
                }
            },
            getRange: function() {
                var me = this;

                function optimze(range) {
                    var child = me.document.body.firstChild,
                        collapsed = range.collapsed;
                    while (child && child.firstChild) {
                        range.setStart(child, 0);
                        child = child.firstChild
                    }
                    if (!range.startContainer) {
                        range.setStart(me.document.body, 0)
                    }
                    if (collapsed) {
                        range.collapse(true)
                    }
                }
                if (me._cachedRange != null) {
                    return this._cachedRange
                }
                var range = new baidu.editor.dom.Range(me.document);
                if (browser.ie9below) {
                    var nativeRange = me.getIERange();
                    if (nativeRange) {
                        try {
                            transformIERangeToRange(nativeRange, range)
                        } catch (e) {
                            optimze(range)
                        }
                    } else {
                        optimze(range)
                    }
                } else {
                    var sel = me.getNative();
                    if (sel && sel.rangeCount) {
                        var firstRange = sel.getRangeAt(0);
                        var lastRange = sel.getRangeAt(sel.rangeCount - 1);
                        range.setStart(firstRange.startContainer, firstRange.startOffset).setEnd(lastRange.endContainer, lastRange.endOffset);
                        if (range.collapsed && domUtils.isBody(range.startContainer) && !range.startOffset) {
                            optimze(range)
                        }
                    } else {
                        if (this._bakRange && domUtils.inDoc(this._bakRange.startContainer, this.document)) {
                            return this._bakRange
                        }
                        optimze(range)
                    }
                }
                return this._bakRange = range
            },
            getStart: function() {
                if (this._cachedStartElement) {
                    return this._cachedStartElement
                }
                var range = browser.ie9below ? this.getIERange() : this.getRange(),
                    tmpRange, start, tmp, parent;
                if (browser.ie9below) {
                    if (!range) {
                        return this.document.body.firstChild
                    }
                    if (range.item) {
                        return range.item(0)
                    }
                    tmpRange = range.duplicate();
                    tmpRange.text.length > 0 && tmpRange.moveStart("character", 1);
                    tmpRange.collapse(1);
                    start = tmpRange.parentElement();
                    parent = tmp = range.parentElement();
                    while (tmp = tmp.parentNode) {
                        if (tmp == start) {
                            start = parent;
                            break
                        }
                    }
                } else {
                    range.shrinkBoundary();
                    start = range.startContainer;
                    if (start.nodeType == 1 && start.hasChildNodes()) {
                        start = start.childNodes[Math.min(start.childNodes.length - 1, range.startOffset)]
                    }
                    if (start.nodeType == 3) {
                        return start.parentNode
                    }
                }
                return start
            },
            getText: function() {
                var nativeSel, nativeRange;
                if (this.isFocus() && (nativeSel = this.getNative())) {
                    nativeRange = browser.ie9below ? nativeSel.createRange() : nativeSel.getRangeAt(0);
                    return browser.ie9below ? nativeRange.text : nativeRange.toString()
                }
                return ""
            },
            clearRange: function() {
                this.getNative()[browser.ie9below ? "empty" : "removeAllRanges"]()
            }
        }
    })();
    (function() {
        var uid = 0,
            _selectionChangeTimer;

        function setValue(form, editor) {
            var textarea;
            if (editor.textarea) {
                if (utils.isString(editor.textarea)) {
                    for (var i = 0, ti, tis = domUtils.getElementsByTagName(form, "textarea"); ti = tis[i++];) {
                        if (ti.id == "ueditor_textarea_" + editor.options.textarea) {
                            textarea = ti;
                            break
                        }
                    }
                } else {
                    textarea = editor.textarea
                }
            }
            if (!textarea) {
                form.appendChild(textarea = domUtils.createElement(document, "textarea", {
                    "name": editor.options.textarea,
                    "id": "ueditor_textarea_" + editor.options.textarea,
                    "style": "display:none"
                }));
                editor.textarea = textarea
            }!textarea.getAttribute("name") && textarea.setAttribute("name", editor.options.textarea);
            textarea.value = editor.hasContents() ? (editor.options.allHtmlEnabled ? editor.getAllHtml() : editor.getContent(null, null, true)) : ""
        }
        function loadPlugins(me) {
            for (var pi in UE.plugins) {
                UE.plugins[pi].call(me)
            }
        }
        function checkCurLang(I18N) {
            for (var lang in I18N) {
                return lang
            }
        }
        function langReadied(me) {
            me.langIsReady = true;
            me.fireEvent("langReady")
        }
        var Editor = UE.Editor = function(options) {
            var me = this;
            me.uid = uid++;
            EventBase.call(me);
            me.commands = {};
            me.options = utils.extend(utils.clone(options || {}), UEDITOR_CONFIG, true);
            me.shortcutkeys = {};
            me.inputRules = [];
            me.outputRules = [];
            me.setOpt(Editor.defaultOptions(me));
            me.loadServerConfig();
            if (!utils.isEmptyObject(UE.I18N)) {
                me.options.lang = checkCurLang(UE.I18N);
                UE.plugin.load(me);
                langReadied(me)
            } else {
                utils.loadFile(document, {
                    src: me.options.langPath + me.options.lang + "/" + me.options.lang + ".js",
                    tag: "script",
                    type: "text/javascript",
                    defer: "defer"
                }, function() {
                    UE.plugin.load(me);
                    langReadied(me)
                })
            }
            UE.instants["ueditorInstant" + me.uid] = me
        };
        Editor.prototype = {
            registerCommand: function(name, obj) {
                this.commands[name] = obj
            },
            ready: function(fn) {
                var me = this;
                if (fn) {
                    me.isReady ? fn.apply(me) : me.addListener("ready", fn)
                }
            },
            setOpt: function(key, val) {
                var obj = {};
                if (utils.isString(key)) {
                    obj[key] = val
                } else {
                    obj = key
                }
                utils.extend(this.options, obj, true)
            },
            getOpt: function(key) {
                return this.options[key]
            },
            destroy: function() {
                var me = this;
                me.fireEvent("destroy");
                var container = me.container.parentNode;
                var textarea = me.textarea;
                if (!textarea) {
                    textarea = document.createElement("textarea");
                    container.parentNode.insertBefore(textarea, container)
                } else {
                    textarea.style.display = ""
                }
                textarea.style.width = me.iframe.offsetWidth + "px";
                textarea.style.height = me.iframe.offsetHeight + "px";
                textarea.value = me.getContent();
                textarea.id = me.key;
                container.innerHTML = "";
                domUtils.remove(container);
                var key = me.key;
                for (var p in me) {
                    if (me.hasOwnProperty(p)) {
                        delete this[p]
                    }
                }
                UE.delEditor(key)
            },
            render: function(container) {
                var me = this,
                    options = me.options,
                    getStyleValue = function(attr) {
                        return parseInt(domUtils.getComputedStyle(container, attr))
                    };
                if (utils.isString(container)) {
                    container = document.getElementById(container)
                }
                if (container) {
                    if (options.initialFrameWidth) {
                        options.minFrameWidth = options.initialFrameWidth
                    } else {
                        options.minFrameWidth = options.initialFrameWidth = container.offsetWidth
                    }
                    if (options.initialFrameHeight) {
                        options.minFrameHeight = options.initialFrameHeight
                    } else {
                        options.initialFrameHeight = options.minFrameHeight = container.offsetHeight
                    }
                    container.style.width = /%$/.test(options.initialFrameWidth) ? "100%" : options.initialFrameWidth - getStyleValue("padding-left") - getStyleValue("padding-right") + "px";
                    container.style.height = /%$/.test(options.initialFrameHeight) ? "100%" : options.initialFrameHeight - getStyleValue("padding-top") - getStyleValue("padding-bottom") + "px";
                    container.style.zIndex = options.zIndex;
                    var html = (ie && browser.version < 9 ? "" : "<!DOCTYPE html>") + "<html xmlns='http://www.w3.org/1999/xhtml' class='view' ><head>" + "<style type='text/css'>" + ".view{padding:0;word-wrap:break-word;cursor:text;height:90%;}\n" + "body{margin:8px;font-family:sans-serif;font-size:16px;}" + "p{margin:5px 0;}</style>" + (options.iframeCssUrl ? "<link rel='stylesheet' type='text/css' href='" + utils.unhtml(options.iframeCssUrl) + "'/>" : "") + (options.initialStyle ? "<style>" + options.initialStyle + "</style>" : "") + "</head><body class='view' ></body>" + "<script type='text/javascript' " + (ie ? "defer='defer'" : "") + " id='_initialScript'>" + "setTimeout(function(){editor = window.parent.UE.instants['ueditorInstant" + me.uid + "'];editor._setup(document);},0);" + "var _tmpScript = document.getElementById('_initialScript');_tmpScript.parentNode.removeChild(_tmpScript);<\/script></html>";
                    container.appendChild(domUtils.createElement(document, "iframe", {
                        id: "ueditor_" + me.uid,
                        width: "100%",
                        height: "100%",
                        frameborder: "0",
                        src: "javascript:void(function(){document.open();" + (options.customDomain && document.domain != location.hostname ? 'document.domain="' + document.domain + '";' : "") + 'document.write("' + html + '");document.close();}())'
                    }));
                    container.style.overflow = "hidden";
                    setTimeout(function() {
                        if (/%$/.test(options.initialFrameWidth)) {
                            options.minFrameWidth = options.initialFrameWidth = container.offsetWidth
                        }
                        if (/%$/.test(options.initialFrameHeight)) {
                            options.minFrameHeight = options.initialFrameHeight = container.offsetHeight;
                            container.style.height = options.initialFrameHeight + "px"
                        }
                    })
                }
            },
            _setup: function(doc) {
                var me = this,
                    options = me.options;
                if (ie) {
                    doc.body.disabled = true;
                    doc.body.contentEditable = true;
                    doc.body.disabled = false
                } else {
                    doc.body.contentEditable = true
                }
                doc.body.spellcheck = false;
                me.document = doc;
                me.window = doc.defaultView || doc.parentWindow;
                me.iframe = me.window.frameElement;
                me.body = doc.body;
                me.selection = new dom.Selection(doc);
                var geckoSel;
                if (browser.gecko && (geckoSel = this.selection.getNative())) {
                    geckoSel.removeAllRanges()
                }
                this._initEvents();
                for (var form = this.iframe.parentNode; !domUtils.isBody(form); form = form.parentNode) {
                    if (form.tagName == "FORM") {
                        me.form = form;
                        if (me.options.autoSyncData) {
                            domUtils.on(me.window, "blur", function() {
                                setValue(form, me)
                            })
                        } else {
                            domUtils.on(form, "submit", function() {
                                setValue(this, me)
                            })
                        }
                        break
                    }
                }
                if (options.initialContent) {
                    if (options.autoClearinitialContent) {
                        var oldExecCommand = me.execCommand;
                        me.execCommand = function() {
                            me.fireEvent("firstBeforeExecCommand");
                            return oldExecCommand.apply(me, arguments)
                        };
                        this._setDefaultContent(options.initialContent)
                    } else {
                        this.setContent(options.initialContent, false, true)
                    }
                }
                if (domUtils.isEmptyNode(me.body)) {
                    me.body.innerHTML = "<p>" + (browser.ie ? "" : "<br/>") + "</p>"
                }
                if (options.focus) {
                    setTimeout(function() {
                        me.focus(me.options.focusInEnd);
                        !me.options.autoClearinitialContent && me._selectionChange()
                    }, 0)
                }
                if (!me.container) {
                    me.container = this.iframe.parentNode
                }
                if (options.fullscreen && me.ui) {
                    me.ui.setFullScreen(true)
                }
                try {
                    me.document.execCommand("2D-position", false, false)
                } catch (e) {}
                try {
                    me.document.execCommand("enableInlineTableEditing", false, false)
                } catch (e) {}
                try {
                    me.document.execCommand("enableObjectResizing", false, false)
                } catch (e) {}
                me._bindshortcutKeys();
                me.isReady = 1;
                me.fireEvent("ready");
                options.onready && options.onready.call(me);
                if (!browser.ie9below) {
                    domUtils.on(me.window, ["blur", "focus"], function(e) {
                        if (e.type == "blur") {
                            me._bakRange = me.selection.getRange();
                            try {
                                me._bakNativeRange = me.selection.getNative().getRangeAt(0);
                                me.selection.getNative().removeAllRanges()
                            } catch (e) {
                                me._bakNativeRange = null
                            }
                        } else {
                            try {
                                me._bakRange && me._bakRange.select()
                            } catch (e) {}
                        }
                    })
                }
                if (browser.gecko && browser.version <= 10902) {
                    me.body.contentEditable = false;
                    setTimeout(function() {
                        me.body.contentEditable = true
                    }, 100);
                    setInterval(function() {
                        me.body.style.height = me.iframe.offsetHeight - 20 + "px"
                    }, 100)
                }!options.isShow && me.setHide();
                options.readonly && me.setDisabled()
            },
            sync: function(formId) {
                var me = this,
                    form = formId ? document.getElementById(formId) : domUtils.findParent(me.iframe.parentNode, function(node) {
                        return node.tagName == "FORM"
                    }, true);
                form && setValue(form, me)
            },
            setHeight: function(height, notSetHeight) {
                if (height !== parseInt(this.iframe.parentNode.style.height)) {
                    this.iframe.parentNode.style.height = height + "px"
                }!notSetHeight && (this.options.minFrameHeight = this.options.initialFrameHeight = height);
                this.body.style.height = height + "px";
                !notSetHeight && this.trigger("setHeight")
            },
            addshortcutkey: function(cmd, keys) {
                var obj = {};
                if (keys) {
                    obj[cmd] = keys
                } else {
                    obj = cmd
                }
                utils.extend(this.shortcutkeys, obj)
            },
            _bindshortcutKeys: function() {
                var me = this,
                    shortcutkeys = this.shortcutkeys;
                me.addListener("keydown", function(type, e) {
                    var keyCode = e.keyCode || e.which;
                    for (var i in shortcutkeys) {
                        var tmp = shortcutkeys[i].split(",");
                        for (var t = 0, ti; ti = tmp[t++];) {
                            ti = ti.split(":");
                            var key = ti[0],
                                param = ti[1];
                            if (/^(ctrl)(\+shift)?\+(\d+)$/.test(key.toLowerCase()) || /^(\d+)$/.test(key)) {
                                if (((RegExp.$1 == "ctrl" ? (e.ctrlKey || e.metaKey) : 0) && (RegExp.$2 != "" ? e[RegExp.$2.slice(1) + "Key"] : 1) && keyCode == RegExp.$3) || keyCode == RegExp.$1) {
                                    if (me.queryCommandState(i, param) != -1) {
                                        me.execCommand(i, param)
                                    }
                                    domUtils.preventDefault(e)
                                }
                            }
                        }
                    }
                })
            },
            getContent: function(cmd, fn, notSetCursor, ignoreBlank, formatter) {
                var me = this;
                if (cmd && utils.isFunction(cmd)) {
                    fn = cmd;
                    cmd = ""
                }
                if (fn ? !fn() : !this.hasContents()) {
                    return ""
                }
                me.fireEvent("beforegetcontent");
                var root = UE.htmlparser(me.body.innerHTML, ignoreBlank);
                me.filterOutputRule(root);
                me.fireEvent("aftergetcontent", cmd, root);
                return root.toHtml(formatter)
            },
            getAllHtml: function() {
                var me = this,
                    headHtml = [],
                    html = "";
                me.fireEvent("getAllHtml", headHtml);
                if (browser.ie && browser.version > 8) {
                    var headHtmlForIE9 = "";
                    utils.each(me.document.styleSheets, function(si) {
                        headHtmlForIE9 += (si.href ? '<link rel="stylesheet" type="text/css" href="' + si.href + '" />' : "<style>" + si.cssText + "</style>")
                    });
                    utils.each(me.document.getElementsByTagName("script"), function(si) {
                        headHtmlForIE9 += si.outerHTML
                    })
                }
                return "<html><head>" + (me.options.charset ? '<meta http-equiv="Content-Type" content="text/html; charset=' + me.options.charset + '"/>' : "") + (headHtmlForIE9 || me.document.getElementsByTagName("head")[0].innerHTML) + headHtml.join("\n") + "</head>" + "<body " + (ie && browser.version < 9 ? 'class="view"' : "") + ">" + me.getContent(null, null, true) + "</body></html>"
            },
            getPlainTxt: function() {
                var reg = new RegExp(domUtils.fillChar, "g"),
                    html = this.body.innerHTML.replace(/[\n\r]/g, "");
                html = html.replace(/<(p|div)[^>]*>(<br\/?>|&nbsp;)<\/\1>/gi, "\n").replace(/<br\/?>/gi, "\n").replace(/<[^>/]+>/g, "").replace(/(\n)?<\/([^>]+)>/g, function(a, b, c) {
                    return dtd.$block[c] ? "\n" : b ? b : ""
                });
                return html.replace(reg, "").replace(/ /g, " ").replace(/&nbsp;/g, " ")
            },
            getContentTxt: function() {
                var reg = new RegExp(domUtils.fillChar, "g");
                return this.body[browser.ie ? "innerText" : "textContent"].replace(reg, "").replace(/ /g, " ")
            },
            setContent: function(html, isAppendTo, notFireSelectionchange) {
                var me = this;
                me.fireEvent("beforesetcontent", html);
                var root = UE.htmlparser(html);
                me.filterInputRule(root);
                html = root.toHtml();
                me.body.innerHTML = (isAppendTo ? me.body.innerHTML : "") + html;

                function isCdataDiv(node) {
                    return node.tagName == "DIV" && node.getAttribute("cdata_tag")
                }
                if (me.options.enterTag == "p") {
                    var child = this.body.firstChild,
                        tmpNode;
                    if (!child || child.nodeType == 1 && (dtd.$cdata[child.tagName] || isCdataDiv(child) || domUtils.isCustomeNode(child)) && child === this.body.lastChild) {
                        this.body.innerHTML = "<p>" + (browser.ie ? "&nbsp;" : "<br/>") + "</p>" + this.body.innerHTML
                    } else {
                        var p = me.document.createElement("p");
                        while (child) {
                            while (child && (child.nodeType == 3 || child.nodeType == 1 && dtd.p[child.tagName] && !dtd.$cdata[child.tagName])) {
                                tmpNode = child.nextSibling;
                                p.appendChild(child);
                                child = tmpNode
                            }
                            if (p.firstChild) {
                                if (!child) {
                                    me.body.appendChild(p);
                                    break
                                } else {
                                    child.parentNode.insertBefore(p, child);
                                    p = me.document.createElement("p")
                                }
                            }
                            child = child.nextSibling
                        }
                    }
                }
                me.fireEvent("aftersetcontent");
                me.fireEvent("contentchange");
                !notFireSelectionchange && me._selectionChange();
                me._bakRange = me._bakIERange = me._bakNativeRange = null;
                var geckoSel;
                if (browser.gecko && (geckoSel = this.selection.getNative())) {
                    geckoSel.removeAllRanges()
                }
                if (me.options.autoSyncData) {
                    me.form && setValue(me.form, me)
                }
            },
            focus: function(toEnd) {
                try {
                    var me = this,
                        rng = me.selection.getRange();
                    if (toEnd) {
                        var node = me.body.lastChild;
                        if (node && node.nodeType == 1 && !dtd.$empty[node.tagName]) {
                            if (domUtils.isEmptyBlock(node)) {
                                rng.setStartAtFirst(node)
                            } else {
                                rng.setStartAtLast(node)
                            }
                            rng.collapse(true)
                        }
                        rng.setCursor(true)
                    } else {
                        if (!rng.collapsed && domUtils.isBody(rng.startContainer) && rng.startOffset == 0) {
                            var node = me.body.firstChild;
                            if (node && node.nodeType == 1 && !dtd.$empty[node.tagName]) {
                                rng.setStartAtFirst(node).collapse(true)
                            }
                        }
                        rng.select(true)
                    }
                    this.fireEvent("focus selectionchange")
                } catch (e) {}
            },
            isFocus: function() {
                return this.selection.isFocus()
            },
            blur: function() {
                var sel = this.selection.getNative();
                if (sel.empty && browser.ie) {
                    var nativeRng = document.body.createTextRange();
                    nativeRng.moveToElementText(document.body);
                    nativeRng.collapse(true);
                    nativeRng.select();
                    sel.empty()
                } else {
                    sel.removeAllRanges()
                }
            },
            _initEvents: function() {
                var me = this,
                    doc = me.document,
                    win = me.window;
                me._proxyDomEvent = utils.bind(me._proxyDomEvent, me);
                domUtils.on(doc, ["click", "contextmenu", "mousedown", "keydown", "keyup", "keypress", "mouseup", "mouseover", "mouseout", "selectstart"], me._proxyDomEvent);
                domUtils.on(win, ["focus", "blur"], me._proxyDomEvent);
                domUtils.on(me.body, "drop", function(e) {
                    if (browser.gecko && e.stopPropagation) {
                        e.stopPropagation()
                    }
                    me.fireEvent("contentchange")
                });
                domUtils.on(doc, ["mouseup", "keydown"], function(evt) {
                    if (evt.type == "keydown" && (evt.ctrlKey || evt.metaKey || evt.shiftKey || evt.altKey)) {
                        return
                    }
                    if (evt.button == 2) {
                        return
                    }
                    me._selectionChange(250, evt)
                })
            },
            _proxyDomEvent: function(evt) {
                if (this.fireEvent("before" + evt.type.replace(/^on/, "").toLowerCase()) === false) {
                    return false
                }
                if (this.fireEvent(evt.type.replace(/^on/, ""), evt) === false) {
                    return false
                }
                return this.fireEvent("after" + evt.type.replace(/^on/, "").toLowerCase())
            },
            _selectionChange: function(delay, evt) {
                var me = this;
                var hackForMouseUp = false;
                var mouseX, mouseY;
                if (browser.ie && browser.version < 9 && evt && evt.type == "mouseup") {
                    var range = this.selection.getRange();
                    if (!range.collapsed) {
                        hackForMouseUp = true;
                        mouseX = evt.clientX;
                        mouseY = evt.clientY
                    }
                }
                clearTimeout(_selectionChangeTimer);
                _selectionChangeTimer = setTimeout(function() {
                    if (!me.selection || !me.selection.getNative()) {
                        return
                    }
                    var ieRange;
                    if (hackForMouseUp && me.selection.getNative().type == "None") {
                        ieRange = me.document.body.createTextRange();
                        try {
                            ieRange.moveToPoint(mouseX, mouseY)
                        } catch (ex) {
                            ieRange = null
                        }
                    }
                    var bakGetIERange;
                    if (ieRange) {
                        bakGetIERange = me.selection.getIERange;
                        me.selection.getIERange = function() {
                            return ieRange
                        }
                    }
                    me.selection.cache();
                    if (bakGetIERange) {
                        me.selection.getIERange = bakGetIERange
                    }
                    if (me.selection._cachedRange && me.selection._cachedStartElement) {
                        me.fireEvent("beforeselectionchange");
                        me.fireEvent("selectionchange", !! evt);
                        me.fireEvent("afterselectionchange");
                        me.selection.clear()
                    }
                }, delay || 50)
            },
            _callCmdFn: function(fnName, args) {
                var cmdName = args[0].toLowerCase(),
                    cmd, cmdFn;
                cmd = this.commands[cmdName] || UE.commands[cmdName];
                cmdFn = cmd && cmd[fnName];
                if ((!cmd || !cmdFn) && fnName == "queryCommandState") {
                    return 0
                } else {
                    if (cmdFn) {
                        return cmdFn.apply(this, args)
                    }
                }
            },
            execCommand: function(cmdName) {
                cmdName = cmdName.toLowerCase();
                var me = this,
                    result, cmd = me.commands[cmdName] || UE.commands[cmdName];
                if (!cmd || !cmd.execCommand) {
                    return null
                }
                if (!cmd.notNeedUndo && !me.__hasEnterExecCommand) {
                    me.__hasEnterExecCommand = true;
                    if (me.queryCommandState.apply(me, arguments) != -1) {
                        me.fireEvent("saveScene");
                        me.fireEvent.apply(me, ["beforeexeccommand", cmdName].concat(arguments));
                        result = this._callCmdFn("execCommand", arguments);
                        me.fireEvent.apply(me, ["afterexeccommand", cmdName].concat(arguments));
                        me.fireEvent("saveScene")
                    }
                    me.__hasEnterExecCommand = false
                } else {
                    result = this._callCmdFn("execCommand", arguments);
                    (!me.__hasEnterExecCommand && !cmd.ignoreContentChange && !me._ignoreContentChange) && me.fireEvent("contentchange")
                }(!me.__hasEnterExecCommand && !cmd.ignoreContentChange && !me._ignoreContentChange) && me._selectionChange();
                return result
            },
            queryCommandState: function(cmdName) {
                return this._callCmdFn("queryCommandState", arguments)
            },
            queryCommandValue: function(cmdName) {
                return this._callCmdFn("queryCommandValue", arguments)
            },
            hasContents: function(tags) {
                if (tags) {
                    for (var i = 0, ci; ci = tags[i++];) {
                        if (this.document.getElementsByTagName(ci).length > 0) {
                            return true
                        }
                    }
                }
                if (!domUtils.isEmptyBlock(this.body)) {
                    return true
                }
                tags = ["div"];
                for (i = 0; ci = tags[i++];) {
                    var nodes = domUtils.getElementsByTagName(this.document, ci);
                    for (var n = 0, cn; cn = nodes[n++];) {
                        if (domUtils.isCustomeNode(cn)) {
                            return true
                        }
                    }
                }
                return false
            },
            reset: function() {
                this.fireEvent("reset")
            },
            setEnabled: function() {
                var me = this,
                    range;
                if (me.body.contentEditable == "false") {
                    me.body.contentEditable = true;
                    range = me.selection.getRange();
                    try {
                        range.moveToBookmark(me.lastBk);
                        delete me.lastBk
                    } catch (e) {
                        range.setStartAtFirst(me.body).collapse(true)
                    }
                    range.select(true);
                    if (me.bkqueryCommandState) {
                        me.queryCommandState = me.bkqueryCommandState;
                        delete me.bkqueryCommandState
                    }
                    if (me.bkqueryCommandValue) {
                        me.queryCommandValue = me.bkqueryCommandValue;
                        delete me.bkqueryCommandValue
                    }
                    me.fireEvent("selectionchange")
                }
            },
            enable: function() {
                return this.setEnabled()
            },
            setDisabled: function(except) {
                var me = this;
                except = except ? utils.isArray(except) ? except : [except] : [];
                if (me.body.contentEditable == "true") {
                    if (!me.lastBk) {
                        me.lastBk = me.selection.getRange().createBookmark(true)
                    }
                    me.body.contentEditable = false;
                    me.bkqueryCommandState = me.queryCommandState;
                    me.bkqueryCommandValue = me.queryCommandValue;
                    me.queryCommandState = function(type) {
                        if (utils.indexOf(except, type) != -1) {
                            return me.bkqueryCommandState.apply(me, arguments)
                        }
                        return -1
                    };
                    me.queryCommandValue = function(type) {
                        if (utils.indexOf(except, type) != -1) {
                            return me.bkqueryCommandValue.apply(me, arguments)
                        }
                        return null
                    };
                    me.fireEvent("selectionchange")
                }
            },
            disable: function(except) {
                return this.setDisabled(except)
            },
            _setDefaultContent: function() {
                function clear() {
                    var me = this;
                    if (me.document.getElementById("initContent")) {
                        me.body.innerHTML = "<p>" + (ie ? "" : "<br/>") + "</p>";
                        me.removeListener("firstBeforeExecCommand focus", clear);
                        setTimeout(function() {
                            me.focus();
                            me._selectionChange()
                        }, 0)
                    }
                }
                return function(cont) {
                    var me = this;
                    me.body.innerHTML = '<p id="initContent">' + cont + "</p>";
                    me.addListener("firstBeforeExecCommand focus", clear)
                }
            }(),
            setShow: function() {
                var me = this,
                    range = me.selection.getRange();
                if (me.container.style.display == "none") {
                    try {
                        range.moveToBookmark(me.lastBk);
                        delete me.lastBk
                    } catch (e) {
                        range.setStartAtFirst(me.body).collapse(true)
                    }
                    setTimeout(function() {
                        range.select(true)
                    }, 100);
                    me.container.style.display = ""
                }
            },
            show: function() {
                return this.setShow()
            },
            setHide: function() {
                var me = this;
                if (!me.lastBk) {
                    me.lastBk = me.selection.getRange().createBookmark(true)
                }
                me.container.style.display = "none"
            },
            hide: function() {
                return this.setHide()
            },
            getLang: function(path) {
                var lang = UE.I18N[this.options.lang];
                if (!lang) {
                    throw Error("not import language file")
                }
                path = (path || "").split(".");
                for (var i = 0, ci; ci = path[i++];) {
                    lang = lang[ci];
                    if (!lang) {
                        break
                    }
                }
                return lang
            },
            getContentLength: function(ingoneHtml, tagNames) {
                var count = this.getContent(false, false, true).length;
                if (ingoneHtml) {
                    tagNames = (tagNames || []).concat(["hr", "img", "iframe"]);
                    count = this.getContentTxt().replace(/[\t\r\n]+/g, "").length;
                    for (var i = 0, ci; ci = tagNames[i++];) {
                        count += this.document.getElementsByTagName(ci).length
                    }
                }
                return count
            },
            addInputRule: function(rule) {
                this.inputRules.push(rule)
            },
            filterInputRule: function(root) {
                for (var i = 0, ci; ci = this.inputRules[i++];) {
                    ci.call(this, root)
                }
            },
            addOutputRule: function(rule) {
                this.outputRules.push(rule)
            },
            filterOutputRule: function(root) {
                for (var i = 0, ci; ci = this.outputRules[i++];) {
                    ci.call(this, root)
                }
            },
            getActionUrl: function(action) {
                var actionName = this.getOpt(action) || action,
                    imageUrl = this.getOpt("imageUrl"),
                    serverUrl = this.getOpt("serverUrl");
                if (!serverUrl && imageUrl) {
                    serverUrl = imageUrl.replace(/^(.*[\/]).+([\.].+)$/, "$1controller$2")
                }
                if (serverUrl) {
                    serverUrl = serverUrl + (serverUrl.indexOf("?") == -1 ? "?" : "&") + "action=" + (actionName || "");
                    return utils.formatUrl(serverUrl)
                } else {
                    return ""
                }
            }
        };
        utils.inherits(Editor, EventBase)
    })();
    UE.Editor.defaultOptions = function(editor) {
        var _url = editor.options.UEDITOR_HOME_URL;
        return {
            isShow: true,
            initialContent: "",
            initialStyle: "",
            autoClearinitialContent: false,
            iframeCssUrl: _url + "themes/iframe.css",
            textarea: "editorValue",
            focus: false,
            focusInEnd: true,
            autoClearEmptyNode: true,
            fullscreen: false,
            readonly: false,
            zIndex: 999,
            imagePopup: true,
            enterTag: "p",
            customDomain: false,
            lang: "zh-cn",
            langPath: _url + "lang/",
            theme: "default",
            themePath: _url + "themes/",
            allHtmlEnabled: false,
            scaleEnabled: false,
            tableNativeEditInFF: false,
            autoSyncData: true,
            fileNameFormat: "{time}{rand:6}"
        }
    };
    (function() {
        UE.Editor.prototype.loadServerConfig = function() {
            var me = this;
            setTimeout(function() {
                try {
                    me.options.imageUrl && me.setOpt("serverUrl", me.options.imageUrl.replace(/^(.*[\/]).+([\.].+)$/, "$1controller$2"));
                    var configUrl = me.getActionUrl("config"),
                        isJsonp = utils.isCrossDomainUrl(configUrl);
                    me._serverConfigLoaded = false;
                    configUrl && UE.ajax.request(configUrl, {
                        "method": "GET",
                        "dataType": isJsonp ? "jsonp" : "",
                        "onsuccess": function(r) {
                            try {
                                var config = isJsonp ? r : eval("(" + r.responseText + ")");
                                utils.extend(me.options, config);
                                me.fireEvent("serverConfigLoaded");
                                me._serverConfigLoaded = true
                            } catch (e) {
                                showErrorMsg(me.getLang("loadconfigFormatError"))
                            }
                        },
                        "onerror": function() {
                            showErrorMsg(me.getLang("loadconfigHttpError"))
                        }
                    })
                } catch (e) {
                    showErrorMsg(me.getLang("loadconfigError"))
                }
            });

            function showErrorMsg(msg) {
                console && console.error(msg)
            }
        };
        UE.Editor.prototype.isServerConfigLoaded = function() {
            var me = this;
            return me._serverConfigLoaded || false
        };
        UE.Editor.prototype.afterConfigReady = function(handler) {
            if (!handler || !utils.isFunction(handler)) {
                return
            }
            var me = this;
            var readyHandler = function() {
                handler.apply(me, arguments);
                me.removeListener("serverConfigLoaded", readyHandler)
            };
            if (me.isServerConfigLoaded()) {
                handler.call(me, "serverConfigLoaded")
            } else {
                me.addListener("serverConfigLoaded", readyHandler)
            }
        }
    })();
    UE.ajax = function() {
        var fnStr = "XMLHttpRequest()";
        try {
            new ActiveXObject("Msxml2.XMLHTTP");
            fnStr = "ActiveXObject('Msxml2.XMLHTTP')"
        } catch (e) {
            try {
                new ActiveXObject("Microsoft.XMLHTTP");
                fnStr = "ActiveXObject('Microsoft.XMLHTTP')"
            } catch (e) {}
        }
        var creatAjaxRequest = new Function("return new " + fnStr);

        function json2str(json) {
            var strArr = [];
            for (var i in json) {
                if (i == "method" || i == "timeout" || i == "async" || i == "dataType" || i == "callback") {
                    continue
                }
                if (json[i] == undefined || json[i] == null) {
                    continue
                }
                if (!((typeof json[i]).toLowerCase() == "function" || (typeof json[i]).toLowerCase() == "object")) {
                    strArr.push(encodeURIComponent(i) + "=" + encodeURIComponent(json[i]))
                } else {
                    if (utils.isArray(json[i])) {
                        for (var j = 0; j < json[i].length; j++) {
                            strArr.push(encodeURIComponent(i) + "[]=" + encodeURIComponent(json[i][j]))
                        }
                    }
                }
            }
            return strArr.join("&")
        }
        function doAjax(url, ajaxOptions) {
            var xhr = creatAjaxRequest(),
                timeIsOut = false,
                defaultAjaxOptions = {
                    method: "POST",
                    timeout: 5000,
                    async: true,
                    data: {},
                    onsuccess: function() {},
                    onerror: function() {}
                };
            if (typeof url === "object") {
                ajaxOptions = url;
                url = ajaxOptions.url
            }
            if (!xhr || !url) {
                return
            }
            var ajaxOpts = ajaxOptions ? utils.extend(defaultAjaxOptions, ajaxOptions) : defaultAjaxOptions;
            var submitStr = json2str(ajaxOpts);
            if (!utils.isEmptyObject(ajaxOpts.data)) {
                submitStr += (submitStr ? "&" : "") + json2str(ajaxOpts.data)
            }
            var timerID = setTimeout(function() {
                if (xhr.readyState != 4) {
                    timeIsOut = true;
                    xhr.abort();
                    clearTimeout(timerID)
                }
            }, ajaxOpts.timeout);
            var method = ajaxOpts.method.toUpperCase();
            var str = url + (url.indexOf("?") == -1 ? "?" : "&") + (method == "POST" ? "" : submitStr + "&noCache=" + +new Date);
            xhr.open(method, str, ajaxOpts.async);
            xhr.onreadystatechange = function() {
                if (xhr.readyState == 4) {
                    if (!timeIsOut && xhr.status == 200) {
                        ajaxOpts.onsuccess(xhr)
                    } else {
                        ajaxOpts.onerror(xhr)
                    }
                }
            };
            if (method == "POST") {
                xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
                xhr.send(submitStr)
            } else {
                xhr.send(null)
            }
        }
        function doJsonp(url, opts) {
            var successhandler = opts.onsuccess ||
                function() {}, scr = document.createElement("SCRIPT"), options = opts || {}, charset = options["charset"], callbackField = options["jsonp"] || "callback", callbackFnName, timeOut = options["timeOut"] || 0, timer, reg = new RegExp("(\\?|&)" + callbackField + "=([^&]*)"), matches;
            if (utils.isFunction(successhandler)) {
                callbackFnName = "bd__editor__" + Math.floor(Math.random() * 2147483648).toString(36);
                window[callbackFnName] = getCallBack(0)
            } else {
                if (utils.isString(successhandler)) {
                    callbackFnName = successhandler
                } else {
                    if (matches = reg.exec(url)) {
                        callbackFnName = matches[2]
                    }
                }
            }
            url = url.replace(reg, "$1" + callbackField + "=" + callbackFnName);
            if (url.search(reg) < 0) {
                url += (url.indexOf("?") < 0 ? "?" : "&") + callbackField + "=" + callbackFnName
            }
            var queryStr = json2str(opts);
            if (!utils.isEmptyObject(opts.data)) {
                queryStr += (queryStr ? "&" : "") + json2str(opts.data)
            }
            if (queryStr) {
                url = url.replace(/\?/, "?" + queryStr + "&")
            }
            scr.onerror = getCallBack(1);
            if (timeOut) {
                timer = setTimeout(getCallBack(1), timeOut)
            }
            createScriptTag(scr, url, charset);

            function createScriptTag(scr, url, charset) {
                scr.setAttribute("type", "text/javascript");
                scr.setAttribute("defer", "defer");
                charset && scr.setAttribute("charset", charset);
                scr.setAttribute("src", url);
                document.getElementsByTagName("head")[0].appendChild(scr)
            }
            function getCallBack(onTimeOut) {
                return function() {
                    try {
                        if (onTimeOut) {
                            options.onerror && options.onerror()
                        } else {
                            try {
                                clearTimeout(timer);
                                successhandler.apply(window, arguments)
                            } catch (e) {}
                        }
                    } catch (exception) {
                        options.onerror && options.onerror.call(window, exception)
                    } finally {
                        options.oncomplete && options.oncomplete.apply(window, arguments);
                        scr.parentNode && scr.parentNode.removeChild(scr);
                        window[callbackFnName] = null;
                        try {
                            delete window[callbackFnName]
                        } catch (e) {}
                    }
                }
            }
        }
        return {
            request: function(url, opts) {
                if (opts && opts.dataType == "jsonp") {
                    doJsonp(url, opts)
                } else {
                    doAjax(url, opts)
                }
            },
            getJSONP: function(url, data, fn) {
                var opts = {
                    "data": data,
                    "oncomplete": fn
                };
                doJsonp(url, opts)
            }
        }
    }();
    var filterWord = UE.filterWord = function() {
        function isWordDocument(str) {
            return /(class="?Mso|style="[^"]*\bmso\-|w:WordDocument|<(v|o):|lang=)/ig.test(str)
        }
        function transUnit(v) {
            v = v.replace(/[\d.]+\w+/g, function(m) {
                return utils.transUnitToPx(m)
            });
            return v
        }
        function filterPasteWord(str) {
            return str.replace(/[\t\r\n]+/g, " ").replace(/<!--[\s\S]*?-->/ig, "").replace(/<v:shape [^>]*>[\s\S]*?.<\/v:shape>/gi, function(str) {
                if (browser.opera) {
                    return ""
                }
                try {
                    if (/Bitmap/i.test(str)) {
                        return ""
                    }
                    var width = str.match(/width:([ \d.]*p[tx])/i)[1],
                        height = str.match(/height:([ \d.]*p[tx])/i)[1],
                        src = str.match(/src=\s*"([^"]*)"/i)[1];
                    return '<img width="' + transUnit(width) + '" height="' + transUnit(height) + '" src="' + src + '" />'
                } catch (e) {
                    return ""
                }
            }).replace(/<\/?div[^>]*>/g, "").replace(/v:\w+=(["']?)[^'"]+\1/g, "").replace(/<(!|script[^>]*>.*?<\/script(?=[>\s])|\/?(\?xml(:\w+)?|xml|meta|link|style|\w+:\w+)(?=[\s\/>]))[^>]*>/gi, "").replace(/<p [^>]*class="?MsoHeading"?[^>]*>(.*?)<\/p>/gi, "<p><strong>$1</strong></p>").replace(/\s+(class|lang|align)\s*=\s*(['"]?)([\w-]+)\2/ig, function(str, name, marks, val) {
                return name == "class" && val == "MsoListParagraph" ? str : ""
            }).replace(/<(font|span)[^>]*>(\s*)<\/\1>/gi, function(a, b, c) {
                return c.replace(/[\t\r\n ]+/g, " ")
            }).replace(/(<[a-z][^>]*)\sstyle=(["'])([^\2]*?)\2/gi, function(str, tag, tmp, style) {
                var n = [],
                    s = style.replace(/^\s+|\s+$/, "").replace(/&#39;/g, "'").replace(/&quot;/gi, "'").replace(/[\d.]+(cm|pt)/g, function(str) {
                        return utils.transUnitToPx(str)
                    }).split(/;\s*/g);
                for (var i = 0, v; v = s[i]; i++) {
                    var name, value, parts = v.split(":");
                    if (parts.length == 2) {
                        name = parts[0].toLowerCase();
                        value = parts[1].toLowerCase();
                        if (/^(background)\w*/.test(name) && value.replace(/(initial|\s)/g, "").length == 0 || /^(margin)\w*/.test(name) && /^0\w+$/.test(value)) {
                            continue
                        }
                        switch (name) {
                            case "mso-padding-alt":
                            case "mso-padding-top-alt":
                            case "mso-padding-right-alt":
                            case "mso-padding-bottom-alt":
                            case "mso-padding-left-alt":
                            case "mso-margin-alt":
                            case "mso-margin-top-alt":
                            case "mso-margin-right-alt":
                            case "mso-margin-bottom-alt":
                            case "mso-margin-left-alt":
                            case "mso-height":
                            case "mso-width":
                            case "mso-vertical-align-alt":
                                if (!/<table/.test(tag)) {
                                    n[i] = name.replace(/^mso-|-alt$/g, "") + ":" + transUnit(value)
                                }
                                continue;
                            case "horiz-align":
                                n[i] = "text-align:" + value;
                                continue;
                            case "vert-align":
                                n[i] = "vertical-align:" + value;
                                continue;
                            case "font-color":
                            case "mso-foreground":
                                n[i] = "color:" + value;
                                continue;
                            case "mso-background":
                            case "mso-highlight":
                                n[i] = "background:" + value;
                                continue;
                            case "mso-default-height":
                                n[i] = "min-height:" + transUnit(value);
                                continue;
                            case "mso-default-width":
                                n[i] = "min-width:" + transUnit(value);
                                continue;
                            case "mso-padding-between-alt":
                                n[i] = "border-collapse:separate;border-spacing:" + transUnit(value);
                                continue;
                            case "text-line-through":
                                if ((value == "single") || (value == "double")) {
                                    n[i] = "text-decoration:line-through"
                                }
                                continue;
                            case "mso-zero-height":
                                if (value == "yes") {
                                    n[i] = "display:none"
                                }
                                continue;
                            case "margin":
                                if (!/[1-9]/.test(value)) {
                                    continue
                                }
                        }
                        if (/^(mso|column|font-emph|lang|layout|line-break|list-image|nav|panose|punct|row|ruby|sep|size|src|tab-|table-border|text-(?:decor|trans)|top-bar|version|vnd|word-break)/.test(name) || /text\-indent|padding|margin/.test(name) && /\-[\d.]+/.test(value)) {
                            continue
                        }
                        n[i] = name + ":" + parts[1]
                    }
                }
                return tag + (n.length ? ' style="' + n.join(";").replace(/;{2,}/g, ";") + '"' : "")
            })
        }
        return function(html) {
            return (isWordDocument(html) ? filterPasteWord(html) : html)
        }
    }();
    (function() {
        var uNode = UE.uNode = function(obj) {
            this.type = obj.type;
            this.data = obj.data;
            this.tagName = obj.tagName;
            this.parentNode = obj.parentNode;
            this.attrs = obj.attrs || {};
            this.children = obj.children
        };
        var notTransAttrs = {
            "href": 1,
            "src": 1,
            "_src": 1,
            "_href": 1,
            "cdata_data": 1
        };
        var notTransTagName = {
            style: 1,
            script: 1
        };
        var indentChar = "    ",
            breakChar = "\n";

        function insertLine(arr, current, begin) {
            arr.push(breakChar);
            return current + (begin ? 1 : -1)
        }
        function insertIndent(arr, current) {
            for (var i = 0; i < current; i++) {
                arr.push(indentChar)
            }
        }
        uNode.createElement = function(html) {
            if (/[<>]/.test(html)) {
                return UE.htmlparser(html).children[0]
            } else {
                return new uNode({
                    type: "element",
                    children: [],
                    tagName: html
                })
            }
        };
        uNode.createText = function(data, noTrans) {
            return new UE.uNode({
                type: "text",
                "data": noTrans ? data : utils.unhtml(data || "")
            })
        };

        function nodeToHtml(node, arr, formatter, current) {
            switch (node.type) {
                case "root":
                    for (var i = 0, ci; ci = node.children[i++];) {
                        if (formatter && ci.type == "element" && !dtd.$inlineWithA[ci.tagName] && i > 1) {
                            insertLine(arr, current, true);
                            insertIndent(arr, current)
                        }
                        nodeToHtml(ci, arr, formatter, current)
                    }
                    break;
                case "text":
                    isText(node, arr);
                    break;
                case "element":
                    isElement(node, arr, formatter, current);
                    break;
                case "comment":
                    isComment(node, arr, formatter)
            }
            return arr
        }
        function isText(node, arr) {
            if (node.parentNode.tagName == "pre") {
                arr.push(node.data)
            } else {
                arr.push(notTransTagName[node.parentNode.tagName] ? utils.html(node.data) : node.data.replace(/[ ]{2}/g, " &nbsp;"))
            }
        }
        function isElement(node, arr, formatter, current) {
            var attrhtml = "";
            if (node.attrs) {
                attrhtml = [];
                var attrs = node.attrs;
                for (var a in attrs) {
                    attrhtml.push(a + (attrs[a] !== undefined ? '="' + (notTransAttrs[a] ? utils.html(attrs[a]).replace(/["]/g, function(a) {
                        return "&quot;"
                    }) : utils.unhtml(attrs[a])) + '"' : ""))
                }
                attrhtml = attrhtml.join(" ")
            }
            arr.push("<" + node.tagName + (attrhtml ? " " + attrhtml : "") + (dtd.$empty[node.tagName] ? "/" : "") + ">");
            if (formatter && !dtd.$inlineWithA[node.tagName] && node.tagName != "pre") {
                if (node.children && node.children.length) {
                    current = insertLine(arr, current, true);
                    insertIndent(arr, current)
                }
            }
            if (node.children && node.children.length) {
                for (var i = 0, ci; ci = node.children[i++];) {
                    if (formatter && ci.type == "element" && !dtd.$inlineWithA[ci.tagName] && i > 1) {
                        insertLine(arr, current);
                        insertIndent(arr, current)
                    }
                    nodeToHtml(ci, arr, formatter, current)
                }
            }
            if (!dtd.$empty[node.tagName]) {
                if (formatter && !dtd.$inlineWithA[node.tagName] && node.tagName != "pre") {
                    if (node.children && node.children.length) {
                        current = insertLine(arr, current);
                        insertIndent(arr, current)
                    }
                }
                arr.push("</" + node.tagName + ">")
            }
        }
        function isComment(node, arr) {
            arr.push("<!--" + node.data + "-->")
        }
        function getNodeById(root, id) {
            var node;
            if (root.type == "element" && root.getAttr("id") == id) {
                return root
            }
            if (root.children && root.children.length) {
                for (var i = 0, ci; ci = root.children[i++];) {
                    if (node = getNodeById(ci, id)) {
                        return node
                    }
                }
            }
        }
        function getNodesByTagName(node, tagName, arr) {
            if (node.type == "element" && node.tagName == tagName) {
                arr.push(node)
            }
            if (node.children && node.children.length) {
                for (var i = 0, ci; ci = node.children[i++];) {
                    getNodesByTagName(ci, tagName, arr)
                }
            }
        }
        function nodeTraversal(root, fn) {
            if (root.children && root.children.length) {
                for (var i = 0, ci; ci = root.children[i];) {
                    nodeTraversal(ci, fn);
                    if (ci.parentNode) {
                        if (ci.children && ci.children.length) {
                            fn(ci)
                        }
                        if (ci.parentNode) {
                            i++
                        }
                    }
                }
            } else {
                fn(root)
            }
        }
        uNode.prototype = {
            toHtml: function(formatter) {
                var arr = [];
                nodeToHtml(this, arr, formatter, 0);
                return arr.join("")
            },
            innerHTML: function(htmlstr) {
                if (this.type != "element" || dtd.$empty[this.tagName]) {
                    return this
                }
                if (utils.isString(htmlstr)) {
                    if (this.children) {
                        for (var i = 0, ci; ci = this.children[i++];) {
                            ci.parentNode = null
                        }
                    }
                    this.children = [];
                    var tmpRoot = UE.htmlparser(htmlstr);
                    for (var i = 0, ci; ci = tmpRoot.children[i++];) {
                        this.children.push(ci);
                        ci.parentNode = this
                    }
                    return this
                } else {
                    var tmpRoot = new UE.uNode({
                        type: "root",
                        children: this.children
                    });
                    return tmpRoot.toHtml()
                }
            },
            innerText: function(textStr, noTrans) {
                if (this.type != "element" || dtd.$empty[this.tagName]) {
                    return this
                }
                if (textStr) {
                    if (this.children) {
                        for (var i = 0, ci; ci = this.children[i++];) {
                            ci.parentNode = null
                        }
                    }
                    this.children = [];
                    this.appendChild(uNode.createText(textStr, noTrans));
                    return this
                } else {
                    return this.toHtml().replace(/<[^>]+>/g, "")
                }
            },
            getData: function() {
                if (this.type == "element") {
                    return ""
                }
                return this.data
            },
            firstChild: function() {
                return this.children ? this.children[0] : null
            },
            lastChild: function() {
                return this.children ? this.children[this.children.length - 1] : null
            },
            previousSibling: function() {
                var parent = this.parentNode;
                for (var i = 0, ci; ci = parent.children[i]; i++) {
                    if (ci === this) {
                        return i == 0 ? null : parent.children[i - 1]
                    }
                }
            },
            nextSibling: function() {
                var parent = this.parentNode;
                for (var i = 0, ci; ci = parent.children[i++];) {
                    if (ci === this) {
                        return parent.children[i]
                    }
                }
            },
            replaceChild: function(target, source) {
                if (this.children) {
                    if (target.parentNode) {
                        target.parentNode.removeChild(target)
                    }
                    for (var i = 0, ci; ci = this.children[i]; i++) {
                        if (ci === source) {
                            this.children.splice(i, 1, target);
                            source.parentNode = null;
                            target.parentNode = this;
                            return target
                        }
                    }
                }
            },
            appendChild: function(node) {
                if (this.type == "root" || (this.type == "element" && !dtd.$empty[this.tagName])) {
                    if (!this.children) {
                        this.children = []
                    }
                    if (node.parentNode) {
                        node.parentNode.removeChild(node)
                    }
                    for (var i = 0, ci; ci = this.children[i]; i++) {
                        if (ci === node) {
                            this.children.splice(i, 1);
                            break
                        }
                    }
                    this.children.push(node);
                    node.parentNode = this;
                    return node
                }
            },
            insertBefore: function(target, source) {
                if (this.children) {
                    if (target.parentNode) {
                        target.parentNode.removeChild(target)
                    }
                    for (var i = 0, ci; ci = this.children[i]; i++) {
                        if (ci === source) {
                            this.children.splice(i, 0, target);
                            target.parentNode = this;
                            return target
                        }
                    }
                }
            },
            insertAfter: function(target, source) {
                if (this.children) {
                    if (target.parentNode) {
                        target.parentNode.removeChild(target)
                    }
                    for (var i = 0, ci; ci = this.children[i]; i++) {
                        if (ci === source) {
                            this.children.splice(i + 1, 0, target);
                            target.parentNode = this;
                            return target
                        }
                    }
                }
            },
            removeChild: function(node, keepChildren) {
                if (this.children) {
                    for (var i = 0, ci; ci = this.children[i]; i++) {
                        if (ci === node) {
                            this.children.splice(i, 1);
                            ci.parentNode = null;
                            if (keepChildren && ci.children && ci.children.length) {
                                for (var j = 0, cj; cj = ci.children[j]; j++) {
                                    this.children.splice(i + j, 0, cj);
                                    cj.parentNode = this
                                }
                            }
                            return ci
                        }
                    }
                }
            },
            getAttr: function(attrName) {
                return this.attrs && this.attrs[attrName.toLowerCase()]
            },
            setAttr: function(attrName, attrVal) {
                if (!attrName) {
                    delete this.attrs;
                    return
                }
                if (!this.attrs) {
                    this.attrs = {}
                }
                if (utils.isObject(attrName)) {
                    for (var a in attrName) {
                        if (!attrName[a]) {
                            delete this.attrs[a]
                        } else {
                            this.attrs[a.toLowerCase()] = attrName[a]
                        }
                    }
                } else {
                    if (!attrVal) {
                        delete this.attrs[attrName]
                    } else {
                        this.attrs[attrName.toLowerCase()] = attrVal
                    }
                }
            },
            getIndex: function() {
                var parent = this.parentNode;
                for (var i = 0, ci; ci = parent.children[i]; i++) {
                    if (ci === this) {
                        return i
                    }
                }
                return -1
            },
            getNodeById: function(id) {
                var node;
                if (this.children && this.children.length) {
                    for (var i = 0, ci; ci = this.children[i++];) {
                        if (node = getNodeById(ci, id)) {
                            return node
                        }
                    }
                }
            },
            getNodesByTagName: function(tagNames) {
                tagNames = utils.trim(tagNames).replace(/[ ]{2,}/g, " ").split(" ");
                var arr = [],
                    me = this;
                utils.each(tagNames, function(tagName) {
                    if (me.children && me.children.length) {
                        for (var i = 0, ci; ci = me.children[i++];) {
                            getNodesByTagName(ci, tagName, arr)
                        }
                    }
                });
                return arr
            },
            getStyle: function(name) {
                var cssStyle = this.getAttr("style");
                if (!cssStyle) {
                    return ""
                }
                var reg = new RegExp("(^|;)\\s*" + name + ":([^;]+)", "i");
                var match = cssStyle.match(reg);
                if (match && match[0]) {
                    return match[2]
                }
                return ""
            },
            setStyle: function(name, val) {
                function exec(name, val) {
                    var reg = new RegExp("(^|;)\\s*" + name + ":([^;]+;?)", "gi");
                    cssStyle = cssStyle.replace(reg, "$1");
                    if (val) {
                        cssStyle = name + ":" + utils.unhtml(val) + ";" + cssStyle
                    }
                }
                var cssStyle = this.getAttr("style");
                if (!cssStyle) {
                    cssStyle = ""
                }
                if (utils.isObject(name)) {
                    for (var a in name) {
                        exec(a, name[a])
                    }
                } else {
                    exec(name, val)
                }
                this.setAttr("style", utils.trim(cssStyle))
            },
            traversal: function(fn) {
                if (this.children && this.children.length) {
                    nodeTraversal(this, fn)
                }
                return this
            }
        }
    })();
    var htmlparser = UE.htmlparser = function(htmlstr, ignoreBlank) {
        var re_tag = /<(?:(?:\/([^>]+)>)|(?:!--([\S|\s]*?)-->)|(?:([^\s\/<>]+)\s*((?:(?:"[^"]*")|(?:'[^']*')|[^"'<>])*)\/?>))/g,
            re_attr = /([\w\-:.]+)(?:(?:\s*=\s*(?:(?:"([^"]*)")|(?:'([^']*)')|([^\s>]+)))|(?=\s|$))/g;
        var allowEmptyTags = {
            b: 1,
            code: 1,
            i: 1,
            u: 1,
            strike: 1,
            s: 1,
            tt: 1,
            strong: 1,
            q: 1,
            samp: 1,
            em: 1,
            span: 1,
            sub: 1,
            img: 1,
            sup: 1,
            font: 1,
            big: 1,
            small: 1,
            iframe: 1,
            a: 1,
            br: 1,
            pre: 1
        };
        htmlstr = htmlstr.replace(new RegExp(domUtils.fillChar, "g"), "");
        if (!ignoreBlank) {
            htmlstr = htmlstr.replace(new RegExp("[\\r\\t\\n" + (ignoreBlank ? "" : " ") + "]*</?(\\w+)\\s*(?:[^>]*)>[\\r\\t\\n" + (ignoreBlank ? "" : " ") + "]*", "g"), function(a, b) {
                if (b && allowEmptyTags[b.toLowerCase()]) {
                    return a.replace(/(^[\n\r]+)|([\n\r]+$)/g, "")
                }
                return a.replace(new RegExp("^[\\r\\n" + (ignoreBlank ? "" : " ") + "]+"), "").replace(new RegExp("[\\r\\n" + (ignoreBlank ? "" : " ") + "]+$"), "")
            })
        }
        var notTransAttrs = {
            "href": 1,
            "src": 1
        };
        var uNode = UE.uNode,
            needParentNode = {
                "td": "tr",
                "tr": ["tbody", "thead", "tfoot"],
                "tbody": "table",
                "th": "tr",
                "thead": "table",
                "tfoot": "table",
                "caption": "table",
                "li": ["ul", "ol"],
                "dt": "dl",
                "dd": "dl",
                "option": "select"
            },
            needChild = {
                "ol": "li",
                "ul": "li"
            };

        function text(parent, data) {
            if (needChild[parent.tagName]) {
                var tmpNode = uNode.createElement(needChild[parent.tagName]);
                parent.appendChild(tmpNode);
                tmpNode.appendChild(uNode.createText(data));
                parent = tmpNode
            } else {
                parent.appendChild(uNode.createText(data))
            }
        }
        function element(parent, tagName, htmlattr) {
            var needParentTag;
            if (needParentTag = needParentNode[tagName]) {
                var tmpParent = parent,
                    hasParent;
                while (tmpParent.type != "root") {
                    if (utils.isArray(needParentTag) ? utils.indexOf(needParentTag, tmpParent.tagName) != -1 : needParentTag == tmpParent.tagName) {
                        parent = tmpParent;
                        hasParent = true;
                        break
                    }
                    tmpParent = tmpParent.parentNode
                }
                if (!hasParent) {
                    parent = element(parent, utils.isArray(needParentTag) ? needParentTag[0] : needParentTag)
                }
            }
            var elm = new uNode({
                parentNode: parent,
                type: "element",
                tagName: tagName.toLowerCase(),
                children: dtd.$empty[tagName] ? null : []
            });
            if (htmlattr) {
                var attrs = {},
                    match;
                while (match = re_attr.exec(htmlattr)) {
                    attrs[match[1].toLowerCase()] = notTransAttrs[match[1].toLowerCase()] ? (match[2] || match[3] || match[4]) : utils.unhtml(match[2] || match[3] || match[4])
                }
                elm.attrs = attrs
            }
            parent.children.push(elm);
            return dtd.$empty[tagName] ? parent : elm
        }
        function comment(parent, data) {
            parent.children.push(new uNode({
                type: "comment",
                data: data,
                parentNode: parent
            }))
        }
        var match, currentIndex = 0,
            nextIndex = 0;
        var root = new uNode({
            type: "root",
            children: []
        });
        var currentParent = root;
        while (match = re_tag.exec(htmlstr)) {
            currentIndex = match.index;
            try {
                if (currentIndex > nextIndex) {
                    text(currentParent, htmlstr.slice(nextIndex, currentIndex))
                }
                if (match[3]) {
                    if (dtd.$cdata[currentParent.tagName]) {
                        text(currentParent, match[0])
                    } else {
                        currentParent = element(currentParent, match[3].toLowerCase(), match[4])
                    }
                } else {
                    if (match[1]) {
                        if (currentParent.type != "root") {
                            if (dtd.$cdata[currentParent.tagName] && !dtd.$cdata[match[1]]) {
                                text(currentParent, match[0])
                            } else {
                                var tmpParent = currentParent;
                                while (currentParent.type == "element" && currentParent.tagName != match[1].toLowerCase()) {
                                    currentParent = currentParent.parentNode;
                                    if (currentParent.type == "root") {
                                        currentParent = tmpParent;
                                        throw "break"
                                    }
                                }
                                currentParent = currentParent.parentNode
                            }
                        }
                    } else {
                        if (match[2]) {
                            comment(currentParent, match[2])
                        }
                    }
                }
            } catch (e) {}
            nextIndex = re_tag.lastIndex
        }
        if (nextIndex < htmlstr.length) {
            text(currentParent, htmlstr.slice(nextIndex))
        }
        return root
    };
    var filterNode = UE.filterNode = function() {
        function filterNode(node, rules) {
            switch (node.type) {
                case "text":
                    break;
                case "element":
                    var val;
                    if (val = rules[node.tagName]) {
                        if (val === "-") {
                            node.parentNode.removeChild(node)
                        } else {
                            if (utils.isFunction(val)) {
                                var parentNode = node.parentNode,
                                    index = node.getIndex();
                                val(node);
                                if (node.parentNode) {
                                    if (node.children) {
                                        for (var i = 0, ci; ci = node.children[i];) {
                                            filterNode(ci, rules);
                                            if (ci.parentNode) {
                                                i++
                                            }
                                        }
                                    }
                                } else {
                                    for (var i = index, ci; ci = parentNode.children[i];) {
                                        filterNode(ci, rules);
                                        if (ci.parentNode) {
                                            i++
                                        }
                                    }
                                }
                            } else {
                                var attrs = val["$"];
                                if (attrs && node.attrs) {
                                    var tmpAttrs = {},
                                        tmpVal;
                                    for (var a in attrs) {
                                        tmpVal = node.getAttr(a);
                                        if (a == "style" && utils.isArray(attrs[a])) {
                                            var tmpCssStyle = [];
                                            utils.each(attrs[a], function(v) {
                                                var tmp;
                                                if (tmp = node.getStyle(v)) {
                                                    tmpCssStyle.push(v + ":" + tmp)
                                                }
                                            });
                                            tmpVal = tmpCssStyle.join(";")
                                        }
                                        if (tmpVal) {
                                            tmpAttrs[a] = tmpVal
                                        }
                                    }
                                    node.attrs = tmpAttrs
                                }
                                if (node.children) {
                                    for (var i = 0, ci; ci = node.children[i];) {
                                        filterNode(ci, rules);
                                        if (ci.parentNode) {
                                            i++
                                        }
                                    }
                                }
                            }
                        }
                    } else {
                        if (dtd.$cdata[node.tagName]) {
                            node.parentNode.removeChild(node)
                        } else {
                            var parentNode = node.parentNode,
                                index = node.getIndex();
                            node.parentNode.removeChild(node, true);
                            for (var i = index, ci; ci = parentNode.children[i];) {
                                filterNode(ci, rules);
                                if (ci.parentNode) {
                                    i++
                                }
                            }
                        }
                    }
                    break;
                case "comment":
                    node.parentNode.removeChild(node)
            }
        }
        return function(root, rules) {
            if (utils.isEmptyObject(rules)) {
                return root
            }
            var val;
            if (val = rules["-"]) {
                utils.each(val.split(" "), function(k) {
                    rules[k] = "-"
                })
            }
            for (var i = 0, ci; ci = root.children[i];) {
                filterNode(ci, rules);
                if (ci.parentNode) {
                    i++
                }
            }
            return root
        }
    }();
    UE.plugin = function() {
        var _plugins = {};
        return {
            register: function(pluginName, fn, oldOptionName, afterDisabled) {
                if (oldOptionName && utils.isFunction(oldOptionName)) {
                    afterDisabled = oldOptionName;
                    oldOptionName = null
                }
                _plugins[pluginName] = {
                    optionName: oldOptionName || pluginName,
                    execFn: fn,
                    afterDisabled: afterDisabled
                }
            },
            load: function(editor) {
                utils.each(_plugins, function(plugin) {
                    var _export = plugin.execFn.call(editor);
                    if (editor.options[plugin.optionName] !== false) {
                        if (_export) {
                            utils.each(_export, function(v, k) {
                                switch (k.toLowerCase()) {
                                    case "shortcutkey":
                                        editor.addshortcutkey(v);
                                        break;
                                    case "bindevents":
                                        utils.each(v, function(fn, eventName) {
                                            editor.addListener(eventName, fn)
                                        });
                                        break;
                                    case "bindmultievents":
                                        utils.each(utils.isArray(v) ? v : [v], function(event) {
                                            var types = utils.trim(event.type).split(/\s+/);
                                            utils.each(types, function(eventName) {
                                                editor.addListener(eventName, event.handler)
                                            })
                                        });
                                        break;
                                    case "commands":
                                        utils.each(v, function(execFn, execName) {
                                            editor.commands[execName] = execFn
                                        });
                                        break;
                                    case "outputrule":
                                        editor.addOutputRule(v);
                                        break;
                                    case "inputrule":
                                        editor.addInputRule(v);
                                        break;
                                    case "defaultoptions":
                                        editor.setOpt(v)
                                }
                            })
                        }
                    } else {
                        if (plugin.afterDisabled) {
                            plugin.afterDisabled.call(editor)
                        }
                    }
                });
                utils.each(UE.plugins, function(plugin) {
                    plugin.call(editor)
                })
            },
            run: function(pluginName, editor) {
                var plugin = _plugins[pluginName];
                if (plugin) {
                    plugin.exeFn.call(editor)
                }
            }
        }
    }();
    var keymap = UE.keymap = {
        "Backspace": 8,
        "Tab": 9,
        "Enter": 13,
        "Shift": 16,
        "Control": 17,
        "Alt": 18,
        "CapsLock": 20,
        "Esc": 27,
        "Spacebar": 32,
        "PageUp": 33,
        "PageDown": 34,
        "End": 35,
        "Home": 36,
        "Left": 37,
        "Up": 38,
        "Right": 39,
        "Down": 40,
        "Insert": 45,
        "Del": 46,
        "NumLock": 144,
        "Cmd": 91,
        "=": 187,
        "-": 189,
        "b": 66,
        "i": 73,
        "z": 90,
        "y": 89,
        "v": 86,
        "x": 88,
        "s": 83,
        "n": 78
    };
    var LocalStorage = UE.LocalStorage = (function() {
        var storage = window.localStorage || getUserData() || null,
            LOCAL_FILE = "localStorage";
        return {
            saveLocalData: function(key, data) {
                if (storage && data) {
                    storage.setItem(key, data);
                    return true
                }
                return false
            },
            getLocalData: function(key) {
                if (storage) {
                    return storage.getItem(key)
                }
                return null
            },
            removeItem: function(key) {
                storage && storage.removeItem(key)
            }
        };

        function getUserData() {
            var container = document.createElement("div");
            container.style.display = "none";
            if (!container.addBehavior) {
                return null
            }
            container.addBehavior("#default#userdata");
            return {
                getItem: function(key) {
                    var result = null;
                    try {
                        document.body.appendChild(container);
                        container.load(LOCAL_FILE);
                        result = container.getAttribute(key);
                        document.body.removeChild(container)
                    } catch (e) {}
                    return result
                },
                setItem: function(key, value) {
                    document.body.appendChild(container);
                    container.setAttribute(key, value);
                    container.save(LOCAL_FILE);
                    document.body.removeChild(container)
                },
                removeItem: function(key) {
                    document.body.appendChild(container);
                    container.removeAttribute(key);
                    container.save(LOCAL_FILE);
                    document.body.removeChild(container)
                }
            }
        }
    })();
    (function() {
        var ROOTKEY = "ueditor_preference";
        UE.Editor.prototype.setPreferences = function(key, value) {
            var obj = {};
            if (utils.isString(key)) {
                obj[key] = value
            } else {
                obj = key
            }
            var data = LocalStorage.getLocalData(ROOTKEY);
            if (data && (data = utils.str2json(data))) {
                utils.extend(data, obj)
            } else {
                data = obj
            }
            data && LocalStorage.saveLocalData(ROOTKEY, utils.json2str(data))
        };
        UE.Editor.prototype.getPreferences = function(key) {
            var data = LocalStorage.getLocalData(ROOTKEY);
            if (data && (data = utils.str2json(data))) {
                return key ? data[key] : data
            }
            return null
        };
        UE.Editor.prototype.removePreferences = function(key) {
            var data = LocalStorage.getLocalData(ROOTKEY);
            if (data && (data = utils.str2json(data))) {
                data[key] = undefined;
                delete data[key]
            }
            data && LocalStorage.saveLocalData(ROOTKEY, utils.json2str(data))
        }
    })();
    UE.plugins["defaultfilter"] = function() {
        var me = this;
        me.setOpt({
            "allowDivTransToP": false,
            "disabledTableInTable": true
        });
        me.addInputRule(function(root) {
            var allowDivTransToP = this.options.allowDivTransToP;
            var val;

            function tdParent(node) {
                while (node && node.type == "element") {
                    if (node.tagName == "td") {
                        return true
                    }
                    node = node.parentNode
                }
                return false
            }
            root.traversal(function(node) {
                if (node.type == "element") {
                    if (!dtd.$cdata[node.tagName] && me.options.autoClearEmptyNode && dtd.$inline[node.tagName] && !dtd.$empty[node.tagName] && (!node.attrs || utils.isEmptyObject(node.attrs))) {
                        if (!node.firstChild()) {
                            node.parentNode.removeChild(node)
                        } else {
                            if (node.tagName == "span" && (!node.attrs || utils.isEmptyObject(node.attrs))) {
                                node.parentNode.removeChild(node, true)
                            }
                        }
                        return
                    }
                    switch (node.tagName) {
                        case "style":
                        case "script":
                            node.setAttr({
                                cdata_tag: node.tagName,
                                cdata_data: (node.innerHTML() || ""),
                                "_ue_custom_node_": "true"
                            });
                            node.tagName = "div";
                            node.innerHTML("");
                            break;
                        case "a":
                            if (val = node.getAttr("href")) {
                                node.setAttr("_href", val)
                            }
                            break;
                        case "img":
                            if (val = node.getAttr("src")) {
                                if (/^data:/.test(val)) {
                                    node.parentNode.removeChild(node);
                                    break
                                }
                            }
                            node.setAttr("_src", node.getAttr("src"));
                            break;
                        case "span":
                            if (browser.webkit && (val = node.getStyle("white-space"))) {
                                if (/nowrap|normal/.test(val)) {
                                    node.setStyle("white-space", "");
                                    if (me.options.autoClearEmptyNode && utils.isEmptyObject(node.attrs)) {
                                        node.parentNode.removeChild(node, true)
                                    }
                                }
                            }
                            val = node.getAttr("id");
                            if (val && /^_baidu_bookmark_/i.test(val)) {
                                node.parentNode.removeChild(node)
                            }
                            break;
                        case "p":
                            if (val = node.getAttr("align")) {
                                node.setAttr("align");
                                node.setStyle("text-align", val)
                            }
                            utils.each(node.children, function(n) {
                                if (n.type == "element" && n.tagName == "p") {
                                    var next = n.nextSibling();
                                    node.parentNode.insertAfter(n, node);
                                    var last = n;
                                    while (next) {
                                        var tmp = next.nextSibling();
                                        node.parentNode.insertAfter(next, last);
                                        last = next;
                                        next = tmp
                                    }
                                    return false
                                }
                            });
                            if (!node.firstChild()) {
                                node.innerHTML(browser.ie ? "&nbsp;" : "<br/>")
                            }
                            break;
                        case "div":
                            if (node.getAttr("cdata_tag")) {
                                break
                            }
                            val = node.getAttr("class");
                            if (val && /^line number\d+/.test(val)) {
                                break
                            }
                            if (!allowDivTransToP) {
                                break
                            }
                            var tmpNode, p = UE.uNode.createElement("p");
                            while (tmpNode = node.firstChild()) {
                                if (tmpNode.type == "text" || !UE.dom.dtd.$block[tmpNode.tagName]) {
                                    p.appendChild(tmpNode)
                                } else {
                                    if (p.firstChild()) {
                                        node.parentNode.insertBefore(p, node);
                                        p = UE.uNode.createElement("p")
                                    } else {
                                        node.parentNode.insertBefore(tmpNode, node)
                                    }
                                }
                            }
                            if (p.firstChild()) {
                                node.parentNode.insertBefore(p, node)
                            }
                            node.parentNode.removeChild(node);
                            break;
                        case "dl":
                            node.tagName = "ul";
                            break;
                        case "dt":
                        case "dd":
                            node.tagName = "li";
                            break;
                        case "li":
                            var className = node.getAttr("class");
                            if (!className || !/list\-/.test(className)) {
                                node.setAttr()
                            }
                            var tmpNodes = node.getNodesByTagName("ol ul");
                            UE.utils.each(tmpNodes, function(n) {
                                node.parentNode.insertAfter(n, node)
                            });
                            break;
                        case "td":
                        case "th":
                        case "caption":
                            if (!node.children || !node.children.length) {
                                node.appendChild(browser.ie11below ? UE.uNode.createText(" ") : UE.uNode.createElement("br"))
                            }
                            break;
                        case "table":
                            if (me.options.disabledTableInTable && tdParent(node)) {
                                node.parentNode.insertBefore(UE.uNode.createText(node.innerText()), node);
                                node.parentNode.removeChild(node)
                            }
                    }
                }
            })
        });
        me.addOutputRule(function(root) {
            var val;
            root.traversal(function(node) {
                if (node.type == "element") {
                    if (me.options.autoClearEmptyNode && dtd.$inline[node.tagName] && !dtd.$empty[node.tagName] && (!node.attrs || utils.isEmptyObject(node.attrs))) {
                        if (!node.firstChild()) {
                            node.parentNode.removeChild(node)
                        } else {
                            if (node.tagName == "span" && (!node.attrs || utils.isEmptyObject(node.attrs))) {
                                node.parentNode.removeChild(node, true)
                            }
                        }
                        return
                    }
                    switch (node.tagName) {
                        case "div":
                            if (val = node.getAttr("cdata_tag")) {
                                node.tagName = val;
                                node.appendChild(UE.uNode.createText(node.getAttr("cdata_data")));
                                node.setAttr({
                                    cdata_tag: "",
                                    cdata_data: "",
                                    "_ue_custom_node_": ""
                                })
                            }
                            break;
                        case "a":
                            if (val = node.getAttr("_href")) {
                                node.setAttr({
                                    "href": utils.html(val),
                                    "_href": ""
                                })
                            }
                            break;
                            break;
                        case "span":
                            val = node.getAttr("id");
                            if (val && /^_baidu_bookmark_/i.test(val)) {
                                node.parentNode.removeChild(node)
                            }
                            break;
                        case "img":
                            if (val = node.getAttr("_src")) {
                                node.setAttr({
                                    "src": node.getAttr("_src"),
                                    "_src": ""
                                })
                            }
                    }
                }
            })
        })
    };
    UE.commands["inserthtml"] = {
        execCommand: function(command, html, notNeedFilter) {
            var me = this,
                range, div;
            if (!html) {
                return
            }
            if (me.fireEvent("beforeinserthtml", html) === true) {
                return
            }
            range = me.selection.getRange();
            div = range.document.createElement("div");
            div.style.display = "inline";
            if (!notNeedFilter) {
                var root = UE.htmlparser(html);
                if (me.options.filterRules) {
                    UE.filterNode(root, me.options.filterRules)
                }
                me.filterInputRule(root);
                html = root.toHtml()
            }
            div.innerHTML = utils.trim(html);
            if (!range.collapsed) {
                var tmpNode = range.startContainer;
                if (domUtils.isFillChar(tmpNode)) {
                    range.setStartBefore(tmpNode)
                }
                tmpNode = range.endContainer;
                if (domUtils.isFillChar(tmpNode)) {
                    range.setEndAfter(tmpNode)
                }
                range.txtToElmBoundary();
                if (range.endContainer && range.endContainer.nodeType == 1) {
                    tmpNode = range.endContainer.childNodes[range.endOffset];
                    if (tmpNode && domUtils.isBr(tmpNode)) {
                        range.setEndAfter(tmpNode)
                    }
                }
                if (range.startOffset == 0) {
                    tmpNode = range.startContainer;
                    if (domUtils.isBoundaryNode(tmpNode, "firstChild")) {
                        tmpNode = range.endContainer;
                        if (range.endOffset == (tmpNode.nodeType == 3 ? tmpNode.nodeValue.length : tmpNode.childNodes.length) && domUtils.isBoundaryNode(tmpNode, "lastChild")) {
                            me.body.innerHTML = "<p>" + (browser.ie ? "" : "<br/>") + "</p>";
                            range.setStart(me.body.firstChild, 0).collapse(true)
                        }
                    }
                }!range.collapsed && range.deleteContents();
                if (range.startContainer.nodeType == 1) {
                    var child = range.startContainer.childNodes[range.startOffset],
                        pre;
                    if (child && domUtils.isBlockElm(child) && (pre = child.previousSibling) && domUtils.isBlockElm(pre)) {
                        range.setEnd(pre, pre.childNodes.length).collapse();
                        while (child.firstChild) {
                            pre.appendChild(child.firstChild)
                        }
                        domUtils.remove(child)
                    }
                }
            }
            var child, parent, pre, tmp, hadBreak = 0,
                nextNode;
            if (range.inFillChar()) {
                child = range.startContainer;
                if (domUtils.isFillChar(child)) {
                    range.setStartBefore(child).collapse(true);
                    domUtils.remove(child)
                } else {
                    if (domUtils.isFillChar(child, true)) {
                        child.nodeValue = child.nodeValue.replace(fillCharReg, "");
                        range.startOffset--;
                        range.collapsed && range.collapse(true)
                    }
                }
            }
            var li = domUtils.findParentByTagName(range.startContainer, "li", true);
            if (li) {
                var next, last;
                while (child = div.firstChild) {
                    while (child && (child.nodeType == 3 || !domUtils.isBlockElm(child) || child.tagName == "HR")) {
                        next = child.nextSibling;
                        range.insertNode(child).collapse();
                        last = child;
                        child = next
                    }
                    if (child) {
                        if (/^(ol|ul)$/i.test(child.tagName)) {
                            while (child.firstChild) {
                                last = child.firstChild;
                                domUtils.insertAfter(li, child.firstChild);
                                li = li.nextSibling
                            }
                            domUtils.remove(child)
                        } else {
                            var tmpLi;
                            next = child.nextSibling;
                            tmpLi = me.document.createElement("li");
                            domUtils.insertAfter(li, tmpLi);
                            tmpLi.appendChild(child);
                            last = child;
                            child = next;
                            li = tmpLi
                        }
                    }
                }
                li = domUtils.findParentByTagName(range.startContainer, "li", true);
                if (domUtils.isEmptyBlock(li)) {
                    domUtils.remove(li)
                }
                if (last) {
                    range.setStartAfter(last).collapse(true).select(true)
                }
            } else {
                while (child = div.firstChild) {
                    if (hadBreak) {
                        var p = me.document.createElement("p");
                        while (child && (child.nodeType == 3 || !dtd.$block[child.tagName])) {
                            nextNode = child.nextSibling;
                            p.appendChild(child);
                            child = nextNode
                        }
                        if (p.firstChild) {
                            child = p
                        }
                    }
                    range.insertNode(child);
                    nextNode = child.nextSibling;
                    if (!hadBreak && child.nodeType == domUtils.NODE_ELEMENT && domUtils.isBlockElm(child)) {
                        parent = domUtils.findParent(child, function(node) {
                            return domUtils.isBlockElm(node)
                        });
                        if (parent && parent.tagName.toLowerCase() != "body" && !(dtd[parent.tagName][child.nodeName] && child.parentNode === parent)) {
                            if (!dtd[parent.tagName][child.nodeName]) {
                                pre = parent
                            } else {
                                tmp = child.parentNode;
                                while (tmp !== parent) {
                                    pre = tmp;
                                    tmp = tmp.parentNode
                                }
                            }
                            domUtils.breakParent(child, pre || tmp);
                            var pre = child.previousSibling;
                            domUtils.trimWhiteTextNode(pre);
                            if (!pre.childNodes.length) {
                                domUtils.remove(pre)
                            }
                            if (!browser.ie && (next = child.nextSibling) && domUtils.isBlockElm(next) && next.lastChild && !domUtils.isBr(next.lastChild)) {
                                next.appendChild(me.document.createElement("br"))
                            }
                            hadBreak = 1
                        }
                    }
                    var next = child.nextSibling;
                    if (!div.firstChild && next && domUtils.isBlockElm(next)) {
                        range.setStart(next, 0).collapse(true);
                        break
                    }
                    range.setEndAfter(child).collapse()
                }
                child = range.startContainer;
                if (nextNode && domUtils.isBr(nextNode)) {
                    domUtils.remove(nextNode)
                }
                if (domUtils.isBlockElm(child) && domUtils.isEmptyNode(child)) {
                    if (nextNode = child.nextSibling) {
                        domUtils.remove(child);
                        if (nextNode.nodeType == 1 && dtd.$block[nextNode.tagName]) {
                            range.setStart(nextNode, 0).collapse(true).shrinkBoundary()
                        }
                    } else {
                        try {
                            child.innerHTML = browser.ie ? domUtils.fillChar : "<br/>"
                        } catch (e) {
                            range.setStartBefore(child);
                            domUtils.remove(child)
                        }
                    }
                }
                try {
                    range.select(true)
                } catch (e) {}
            }
            setTimeout(function() {
                range = me.selection.getRange();
                range.scrollToView(me.autoHeightEnabled, me.autoHeightEnabled ? domUtils.getXY(me.iframe).y : 0);
                me.fireEvent("afterinserthtml", html)
            }, 200)
        }
    };
    UE.plugins["autotypeset"] = function() {
        this.setOpt({
            "autotypeset": {
                mergeEmptyline: true,
                removeClass: true,
                removeEmptyline: false,
                textAlign: "left",
                imageBlockLine: "center",
                pasteFilter: false,
                clearFontSize: false,
                clearFontFamily: false,
                removeEmptyNode: false,
                removeTagNames: utils.extend({
                    div: 1
                }, dtd.$removeEmpty),
                indent: false,
                indentValue: "2em",
                bdc2sb: false,
                tobdc: false
            }
        });
        var me = this,
            opt = me.options.autotypeset,
            remainClass = {
                "selectTdClass": 1,
                "pagebreak": 1,
                "anchorclass": 1
            },
            remainTag = {
                "li": 1
            },
            tags = {
                div: 1,
                p: 1,
                blockquote: 1,
                center: 1,
                h1: 1,
                h2: 1,
                h3: 1,
                h4: 1,
                h5: 1,
                h6: 1,
                span: 1
            },
            highlightCont;
        if (!opt) {
            return
        }
        readLocalOpts();

        function isLine(node, notEmpty) {
            if (!node || node.nodeType == 3) {
                return 0
            }
            if (domUtils.isBr(node)) {
                return 1
            }
            if (node && node.parentNode && tags[node.tagName.toLowerCase()]) {
                if (highlightCont && highlightCont.contains(node) || node.getAttribute("pagebreak")) {
                    return 0
                }
                return notEmpty ? !domUtils.isEmptyBlock(node) : domUtils.isEmptyBlock(node, new RegExp("[\\s" + domUtils.fillChar + "]", "g"))
            }
        }
        function removeNotAttributeSpan(node) {
            if (!node.style.cssText) {
                domUtils.removeAttributes(node, ["style"]);
                if (node.tagName.toLowerCase() == "span" && domUtils.hasNoAttributes(node)) {
                    domUtils.remove(node, true)
                }
            }
        }
        function autotype(type, html) {
            var me = this,
                cont;
            if (html) {
                if (!opt.pasteFilter) {
                    return
                }
                cont = me.document.createElement("div");
                cont.innerHTML = html.html
            } else {
                cont = me.document.body
            }
            var nodes = domUtils.getElementsByTagName(cont, "*");
            for (var i = 0, ci; ci = nodes[i++];) {
                if (me.fireEvent("excludeNodeinautotype", ci) === true) {
                    continue
                }
                if (opt.clearFontSize && ci.style.fontSize) {
                    domUtils.removeStyle(ci, "font-size");
                    removeNotAttributeSpan(ci)
                }
                if (opt.clearFontFamily && ci.style.fontFamily) {
                    domUtils.removeStyle(ci, "font-family");
                    removeNotAttributeSpan(ci)
                }
                if (isLine(ci)) {
                    if (opt.mergeEmptyline) {
                        var next = ci.nextSibling,
                            tmpNode, isBr = domUtils.isBr(ci);
                        while (isLine(next)) {
                            tmpNode = next;
                            next = tmpNode.nextSibling;
                            if (isBr && (!next || next && !domUtils.isBr(next))) {
                                break
                            }
                            domUtils.remove(tmpNode)
                        }
                    }
                    if (opt.removeEmptyline && domUtils.inDoc(ci, cont) && !remainTag[ci.parentNode.tagName.toLowerCase()]) {
                        if (domUtils.isBr(ci)) {
                            next = ci.nextSibling;
                            if (next && !domUtils.isBr(next)) {
                                continue
                            }
                        }
                        domUtils.remove(ci);
                        continue
                    }
                }
                if (isLine(ci, true) && ci.tagName != "SPAN") {
                    if (opt.indent) {
                        ci.style.textIndent = opt.indentValue
                    }
                    if (opt.textAlign) {
                        ci.style.textAlign = opt.textAlign
                    }
                }
                if (opt.removeClass && ci.className && !remainClass[ci.className.toLowerCase()]) {
                    if (highlightCont && highlightCont.contains(ci)) {
                        continue
                    }
                    domUtils.removeAttributes(ci, ["class"])
                }
                if (opt.imageBlockLine && ci.tagName.toLowerCase() == "img" && !ci.getAttribute("emotion")) {
                    if (html) {
                        var img = ci;
                        switch (opt.imageBlockLine) {
                            case "left":
                            case "right":
                            case "none":
                                var pN = img.parentNode,
                                    tmpNode, pre, next;
                                while (dtd.$inline[pN.tagName] || pN.tagName == "A") {
                                    pN = pN.parentNode
                                }
                                tmpNode = pN;
                                if (tmpNode.tagName == "P" && domUtils.getStyle(tmpNode, "text-align") == "center") {
                                    if (!domUtils.isBody(tmpNode) && domUtils.getChildCount(tmpNode, function(node) {
                                            return !domUtils.isBr(node) && !domUtils.isWhitespace(node)
                                        }) == 1) {
                                        pre = tmpNode.previousSibling;
                                        next = tmpNode.nextSibling;
                                        if (pre && next && pre.nodeType == 1 && next.nodeType == 1 && pre.tagName == next.tagName && domUtils.isBlockElm(pre)) {
                                            pre.appendChild(tmpNode.firstChild);
                                            while (next.firstChild) {
                                                pre.appendChild(next.firstChild)
                                            }
                                            domUtils.remove(tmpNode);
                                            domUtils.remove(next)
                                        } else {
                                            domUtils.setStyle(tmpNode, "text-align", "")
                                        }
                                    }
                                }
                                domUtils.setStyle(img, "float", opt.imageBlockLine);
                                break;
                            case "center":
                                if (me.queryCommandValue("imagefloat") != "center") {
                                    pN = img.parentNode;
                                    domUtils.setStyle(img, "float", "none");
                                    tmpNode = img;
                                    while (pN && domUtils.getChildCount(pN, function(node) {
                                        return !domUtils.isBr(node) && !domUtils.isWhitespace(node)
                                    }) == 1 && (dtd.$inline[pN.tagName] || pN.tagName == "A")) {
                                        tmpNode = pN;
                                        pN = pN.parentNode
                                    }
                                    var pNode = me.document.createElement("p");
                                    domUtils.setAttributes(pNode, {
                                        style: "text-align:center"
                                    });
                                    tmpNode.parentNode.insertBefore(pNode, tmpNode);
                                    pNode.appendChild(tmpNode);
                                    domUtils.setStyle(tmpNode, "float", "")
                                }
                        }
                    } else {
                        var range = me.selection.getRange();
                        range.selectNode(ci).select();
                        me.execCommand("imagefloat", opt.imageBlockLine)
                    }
                }
                if (opt.removeEmptyNode) {
                    if (opt.removeTagNames[ci.tagName.toLowerCase()] && domUtils.hasNoAttributes(ci) && domUtils.isEmptyBlock(ci)) {
                        domUtils.remove(ci)
                    }
                }
            }
            if (opt.tobdc) {
                var root = UE.htmlparser(cont.innerHTML);
                root.traversal(function(node) {
                    if (node.type == "text") {
                        node.data = ToDBC(node.data)
                    }
                });
                cont.innerHTML = root.toHtml()
            }
            if (opt.bdc2sb) {
                var root = UE.htmlparser(cont.innerHTML);
                root.traversal(function(node) {
                    if (node.type == "text") {
                        node.data = DBC2SB(node.data)
                    }
                });
                cont.innerHTML = root.toHtml()
            }
            if (html) {
                html.html = cont.innerHTML
            }
        }
        if (opt.pasteFilter) {
            me.addListener("beforepaste", autotype)
        }
        function DBC2SB(str) {
            var result = "";
            for (var i = 0; i < str.length; i++) {
                var code = str.charCodeAt(i);
                if (code >= 65281 && code <= 65373) {
                    result += String.fromCharCode(str.charCodeAt(i) - 65248)
                } else {
                    if (code == 12288) {
                        result += String.fromCharCode(str.charCodeAt(i) - 12288 + 32)
                    } else {
                        result += str.charAt(i)
                    }
                }
            }
            return result
        }
        function ToDBC(txtstring) {
            txtstring = utils.html(txtstring);
            var tmp = "";
            var mark = "";
            for (var i = 0; i < txtstring.length; i++) {
                if (txtstring.charCodeAt(i) == 32) {
                    tmp = tmp + String.fromCharCode(12288)
                } else {
                    if (txtstring.charCodeAt(i) < 127) {
                        tmp = tmp + String.fromCharCode(txtstring.charCodeAt(i) + 65248)
                    } else {
                        tmp += txtstring.charAt(i)
                    }
                }
            }
            return tmp
        }
        function readLocalOpts() {
            var cookieOpt = me.getPreferences("autotypeset");
            utils.extend(me.options.autotypeset, cookieOpt)
        }
        me.commands["autotypeset"] = {
            execCommand: function() {
                me.removeListener("beforepaste", autotype);
                if (opt.pasteFilter) {
                    me.addListener("beforepaste", autotype)
                }
                autotype.call(me)
            }
        }
    };
    UE.plugin.register("autosubmit", function() {
        return {
            shortcutkey: {
                "autosubmit": "ctrl+13"
            },
            commands: {
                "autosubmit": {
                    execCommand: function() {
                        var me = this,
                            form = domUtils.findParentByTagName(me.iframe, "form", false);
                        if (form) {
                            if (me.fireEvent("beforesubmit") === false) {
                                return
                            }
                            me.sync();
                            form.submit()
                        }
                    }
                }
            }
        }
    });
    UE.plugin.register("background", function() {
        var me = this,
            cssRuleId = "editor_background",
            isSetColored, reg = new RegExp("body[\\s]*\\{(.+)\\}", "i");

        function stringToObj(str) {
            var obj = {},
                styles = str.split(";");
            utils.each(styles, function(v) {
                var index = v.indexOf(":"),
                    key = utils.trim(v.substr(0, index)).toLowerCase();
                key && (obj[key] = utils.trim(v.substr(index + 1) || ""))
            });
            return obj
        }
        function setBackground(obj) {
            if (obj) {
                var styles = [];
                for (var name in obj) {
                    if (obj.hasOwnProperty(name)) {
                        styles.push(name + ":" + obj[name] + "; ")
                    }
                }
                utils.cssRule(cssRuleId, styles.length ? ("body{" + styles.join("") + "}") : "", me.document)
            } else {
                utils.cssRule(cssRuleId, "", me.document)
            }
        }
        var orgFn = me.hasContents;
        me.hasContents = function() {
            if (me.queryCommandValue("background")) {
                return true
            }
            return orgFn.apply(me, arguments)
        };
        return {
            bindEvents: {
                "getAllHtml": function(type, headHtml) {
                    var body = this.body,
                        su = domUtils.getComputedStyle(body, "background-image"),
                        url = "";
                    if (su.indexOf(me.options.imagePath) > 0) {
                        url = su.substring(su.indexOf(me.options.imagePath), su.length - 1).replace(/"|\(|\)/ig, "")
                    } else {
                        url = su != "none" ? su.replace(/url\("?|"?\)/ig, "") : ""
                    }
                    var html = '<style type="text/css">body{';
                    var bgObj = {
                        "background-color": domUtils.getComputedStyle(body, "background-color") || "#ffffff",
                        "background-image": url ? "url(" + url + ")" : "",
                        "background-repeat": domUtils.getComputedStyle(body, "background-repeat") || "",
                        "background-position": browser.ie ? (domUtils.getComputedStyle(body, "background-position-x") + " " + domUtils.getComputedStyle(body, "background-position-y")) : domUtils.getComputedStyle(body, "background-position"),
                        "height": domUtils.getComputedStyle(body, "height")
                    };
                    for (var name in bgObj) {
                        if (bgObj.hasOwnProperty(name)) {
                            html += name + ":" + bgObj[name] + "; "
                        }
                    }
                    html += "}</style> ";
                    headHtml.push(html)
                },
                "aftersetcontent": function() {
                    if (isSetColored == false) {
                        setBackground()
                    }
                }
            },
            inputRule: function(root) {
                isSetColored = false;
                utils.each(root.getNodesByTagName("p"), function(p) {
                    var styles = p.getAttr("data-background");
                    if (styles) {
                        isSetColored = true;
                        setBackground(stringToObj(styles));
                        p.parentNode.removeChild(p)
                    }
                })
            },
            outputRule: function(root) {
                var me = this,
                    styles = (utils.cssRule(cssRuleId, me.document) || "").replace(/[\n\r]+/g, "").match(reg);
                if (styles) {
                    root.appendChild(UE.uNode.createElement('<p style="display:none;" data-background="' + utils.trim(styles[1].replace(/"/g, "").replace(/[\s]+/g, " ")) + '"><br/></p>'))
                }
            },
            commands: {
                "background": {
                    execCommand: function(cmd, obj) {
                        setBackground(obj)
                    },
                    queryCommandValue: function() {
                        var me = this,
                            styles = (utils.cssRule(cssRuleId, me.document) || "").replace(/[\n\r]+/g, "").match(reg);
                        return styles ? stringToObj(styles[1]) : null
                    },
                    notNeedUndo: true
                }
            }
        }
    });
    UE.commands["imagefloat"] = {
        execCommand: function(cmd, align) {
            var me = this,
                range = me.selection.getRange();
            if (!range.collapsed) {
                var img = range.getClosedNode();
                if (img && img.tagName == "IMG") {
                    switch (align) {
                        case "left":
                        case "right":
                        case "none":
                            var pN = img.parentNode,
                                tmpNode, pre, next;
                            while (dtd.$inline[pN.tagName] || pN.tagName == "A") {
                                pN = pN.parentNode
                            }
                            tmpNode = pN;
                            if (tmpNode.tagName == "P" && domUtils.getStyle(tmpNode, "text-align") == "center") {
                                if (!domUtils.isBody(tmpNode) && domUtils.getChildCount(tmpNode, function(node) {
                                        return !domUtils.isBr(node) && !domUtils.isWhitespace(node)
                                    }) == 1) {
                                    pre = tmpNode.previousSibling;
                                    next = tmpNode.nextSibling;
                                    if (pre && next && pre.nodeType == 1 && next.nodeType == 1 && pre.tagName == next.tagName && domUtils.isBlockElm(pre)) {
                                        pre.appendChild(tmpNode.firstChild);
                                        while (next.firstChild) {
                                            pre.appendChild(next.firstChild)
                                        }
                                        domUtils.remove(tmpNode);
                                        domUtils.remove(next)
                                    } else {
                                        domUtils.setStyle(tmpNode, "text-align", "")
                                    }
                                }
                                range.selectNode(img).select()
                            }
                            domUtils.setStyle(img, "float", align == "none" ? "" : align);
                            if (align == "none") {
                                domUtils.removeAttributes(img, "align")
                            }
                            break;
                        case "center":
                            if (me.queryCommandValue("imagefloat") != "center") {
                                pN = img.parentNode;
                                domUtils.setStyle(img, "float", "");
                                domUtils.removeAttributes(img, "align");
                                tmpNode = img;
                                while (pN && domUtils.getChildCount(pN, function(node) {
                                    return !domUtils.isBr(node) && !domUtils.isWhitespace(node)
                                }) == 1 && (dtd.$inline[pN.tagName] || pN.tagName == "A")) {
                                    tmpNode = pN;
                                    pN = pN.parentNode
                                }
                                range.setStartBefore(tmpNode).setCursor(false);
                                pN = me.document.createElement("div");
                                pN.appendChild(tmpNode);
                                domUtils.setStyle(tmpNode, "float", "");
                                me.execCommand("insertHtml", '<p id="_img_parent_tmp" style="text-align:center">' + pN.innerHTML + "</p>");
                                tmpNode = me.document.getElementById("_img_parent_tmp");
                                tmpNode.removeAttribute("id");
                                tmpNode = tmpNode.firstChild;
                                range.selectNode(tmpNode).select();
                                next = tmpNode.parentNode.nextSibling;
                                if (next && domUtils.isEmptyNode(next)) {
                                    domUtils.remove(next)
                                }
                            }
                            break
                    }
                }
            }
        },
        queryCommandValue: function() {
            var range = this.selection.getRange(),
                startNode, floatStyle;
            if (range.collapsed) {
                return "none"
            }
            startNode = range.getClosedNode();
            if (startNode && startNode.nodeType == 1 && startNode.tagName == "IMG") {
                floatStyle = domUtils.getComputedStyle(startNode, "float") || startNode.getAttribute("align");
                if (floatStyle == "none") {
                    floatStyle = domUtils.getComputedStyle(startNode.parentNode, "text-align") == "center" ? "center" : floatStyle
                }
                return {
                    left: 1,
                    right: 1,
                    center: 1
                }[floatStyle] ? floatStyle : "none"
            }
            return "none"
        },
        queryCommandState: function() {
            var range = this.selection.getRange(),
                startNode;
            if (range.collapsed) {
                return -1
            }
            startNode = range.getClosedNode();
            if (startNode && startNode.nodeType == 1 && startNode.tagName == "IMG") {
                return 0
            }
            return -1
        }
    };
    UE.commands["insertimage"] = {
        execCommand: function(cmd, opt) {
            opt = utils.isArray(opt) ? opt : [opt];
            if (!opt.length) {
                return
            }
            var me = this,
                range = me.selection.getRange(),
                img = range.getClosedNode();
            if (me.fireEvent("beforeinsertimage", opt) === true) {
                return
            }
            function unhtmlData(imgCi) {
                utils.each("width,height,border,hspace,vspace".split(","), function(item) {
                    if (imgCi[item]) {
                        imgCi[item] = parseInt(imgCi[item], 10) || 0
                    }
                });
                utils.each("src,_src".split(","), function(item) {
                    if (imgCi[item]) {
                        imgCi[item] = utils.unhtmlForUrl(imgCi[item])
                    }
                });
                utils.each("title,alt".split(","), function(item) {
                    if (imgCi[item]) {
                        imgCi[item] = utils.unhtml(imgCi[item])
                    }
                })
            }
            if (img && /img/i.test(img.tagName) && (img.className != "edui-faked-video" || img.className.indexOf("edui-upload-video") != -1) && !img.getAttribute("word_img")) {
                var first = opt.shift();
                var floatStyle = first["floatStyle"];
                delete first["floatStyle"];
                domUtils.setAttributes(img, first);
                me.execCommand("imagefloat", floatStyle);
                if (opt.length > 0) {
                    range.setStartAfter(img).setCursor(false, true);
                    me.execCommand("insertimage", opt)
                }
            } else {
                var html = [],
                    str = "",
                    ci;
                ci = opt[0];
                if (opt.length == 1) {
                    unhtmlData(ci);
                    str = '<img src="' + ci.src + '" ' + (ci._src ? ' _src="' + ci._src + '" ' : "") + (ci.width ? 'width="' + ci.width + '" ' : "") + (ci.height ? ' height="' + ci.height + '" ' : "") + (ci["floatStyle"] == "left" || ci["floatStyle"] == "right" ? ' style="float:' + ci["floatStyle"] + ';"' : "") + (ci.title && ci.title != "" ? ' title="' + ci.title + '"' : "") + (ci.border && ci.border != "0" ? ' border="' + ci.border + '"' : "") + (ci.alt && ci.alt != "" ? ' alt="' + ci.alt + '"' : "") + (ci.hspace && ci.hspace != "0" ? ' hspace = "' + ci.hspace + '"' : "") + (ci.vspace && ci.vspace != "0" ? ' vspace = "' + ci.vspace + '"' : "") + "/>";
                    if (ci["floatStyle"] == "center") {
                        str = '<p style="text-align: center">' + str + "</p>"
                    }
                    html.push(str)
                } else {
                    for (var i = 0; ci = opt[i++];) {
                        unhtmlData(ci);
                        str = "<p " + (ci["floatStyle"] == "center" ? 'style="text-align: center" ' : "") + '><img src="' + ci.src + '" ' + (ci.width ? 'width="' + ci.width + '" ' : "") + (ci._src ? ' _src="' + ci._src + '" ' : "") + (ci.height ? ' height="' + ci.height + '" ' : "") + ' style="' + (ci["floatStyle"] && ci["floatStyle"] != "center" ? "float:" + ci["floatStyle"] + ";" : "") + (ci.border || "") + '" ' + (ci.title ? ' title="' + ci.title + '"' : "") + " /></p>";
                        html.push(str)
                    }
                }
                me.execCommand("insertHtml", html.join(""))
            }
            me.fireEvent("afterinsertimage", opt)
        }
    };
    UE.plugins["justify"] = function() {
        var me = this,
            block = domUtils.isBlockElm,
            defaultValue = {
                left: 1,
                right: 1,
                center: 1,
                justify: 1
            },
            doJustify = function(range, style) {
                var bookmark = range.createBookmark(),
                    filterFn = function(node) {
                        return node.nodeType == 1 ? node.tagName.toLowerCase() != "br" && !domUtils.isBookmarkNode(node) : !domUtils.isWhitespace(node)
                    };
                range.enlarge(true);
                var bookmark2 = range.createBookmark(),
                    current = domUtils.getNextDomNode(bookmark2.start, false, filterFn),
                    tmpRange = range.cloneRange(),
                    tmpNode;
                while (current && !(domUtils.getPosition(current, bookmark2.end) & domUtils.POSITION_FOLLOWING)) {
                    if (current.nodeType == 3 || !block(current)) {
                        tmpRange.setStartBefore(current);
                        while (current && current !== bookmark2.end && !block(current)) {
                            tmpNode = current;
                            current = domUtils.getNextDomNode(current, false, null, function(node) {
                                return !block(node)
                            })
                        }
                        tmpRange.setEndAfter(tmpNode);
                        var common = tmpRange.getCommonAncestor();
                        if (!domUtils.isBody(common) && block(common)) {
                            domUtils.setStyles(common, utils.isString(style) ? {
                                "text-align": style
                            } : style);
                            current = common
                        } else {
                            var p = range.document.createElement("p");
                            domUtils.setStyles(p, utils.isString(style) ? {
                                "text-align": style
                            } : style);
                            var frag = tmpRange.extractContents();
                            p.appendChild(frag);
                            tmpRange.insertNode(p);
                            current = p
                        }
                        current = domUtils.getNextDomNode(current, false, filterFn)
                    } else {
                        current = domUtils.getNextDomNode(current, true, filterFn)
                    }
                }
                return range.moveToBookmark(bookmark2).moveToBookmark(bookmark)
            };
        UE.commands["justify"] = {
            execCommand: function(cmdName, align) {
                var range = this.selection.getRange(),
                    txt;
                if (range.collapsed) {
                    txt = this.document.createTextNode("p");
                    range.insertNode(txt)
                }
                doJustify(range, align);
                if (txt) {
                    range.setStartBefore(txt).collapse(true);
                    domUtils.remove(txt)
                }
                range.select();
                return true
            },
            queryCommandValue: function() {
                var startNode = this.selection.getStart(),
                    value = domUtils.getComputedStyle(startNode, "text-align");
                return defaultValue[value] ? value : "left"
            },
            queryCommandState: function() {
                var start = this.selection.getStart(),
                    cell = start && domUtils.findParentByTagName(start, ["td", "th", "caption"], true);
                return cell ? -1 : 0
            }
        }
    };
    UE.plugins["font"] = function() {
        var me = this,
            fonts = {
                "forecolor": "color",
                "backcolor": "background-color",
                "fontsize": "font-size",
                "fontfamily": "font-family",
                "underline": "text-decoration",
                "strikethrough": "text-decoration",
                "fontborder": "border"
            },
            needCmd = {
                "underline": 1,
                "strikethrough": 1,
                "fontborder": 1
            },
            needSetChild = {
                "forecolor": "color",
                "backcolor": "background-color",
                "fontsize": "font-size",
                "fontfamily": "font-family"
            };
        me.setOpt({
            "fontfamily": [{
                name: "songti",
                val: "宋体,SimSun"
            }, {
                name: "yahei",
                val: "微软雅黑,Microsoft YaHei"
            }, {
                name: "kaiti",
                val: "楷体,楷体_GB2312, SimKai"
            }, {
                name: "heiti",
                val: "黑体, SimHei"
            }, {
                name: "lishu",
                val: "隶书, SimLi"
            }, {
                name: "andaleMono",
                val: "andale mono"
            }, {
                name: "arial",
                val: "arial, helvetica,sans-serif"
            }, {
                name: "arialBlack",
                val: "arial black,avant garde"
            }, {
                name: "comicSansMs",
                val: "comic sans ms"
            }, {
                name: "impact",
                val: "impact,chicago"
            }, {
                name: "timesNewRoman",
                val: "times new roman"
            }],
            "fontsize": [10, 11, 12, 14, 16, 18, 20, 24, 36]
        });

        function mergeWithParent(node) {
            var parent;
            while (parent = node.parentNode) {
                if (parent.tagName == "SPAN" && domUtils.getChildCount(parent, function(child) {
                        return !domUtils.isBookmarkNode(child) && !domUtils.isBr(child)
                    }) == 1) {
                    parent.style.cssText += node.style.cssText;
                    domUtils.remove(node, true);
                    node = parent
                } else {
                    break
                }
            }
        }
        function mergeChild(rng, cmdName, value) {
            if (needSetChild[cmdName]) {
                rng.adjustmentBoundary();
                if (!rng.collapsed && rng.startContainer.nodeType == 1) {
                    var start = rng.startContainer.childNodes[rng.startOffset];
                    if (start && domUtils.isTagNode(start, "span")) {
                        var bk = rng.createBookmark();
                        utils.each(domUtils.getElementsByTagName(start, "span"), function(span) {
                            if (!span.parentNode || domUtils.isBookmarkNode(span)) {
                                return
                            }
                            if (cmdName == "backcolor" && domUtils.getComputedStyle(span, "background-color").toLowerCase() === value) {
                                return
                            }
                            domUtils.removeStyle(span, needSetChild[cmdName]);
                            if (span.style.cssText.replace(/^\s+$/, "").length == 0) {
                                domUtils.remove(span, true)
                            }
                        });
                        rng.moveToBookmark(bk)
                    }
                }
            }
        }
        function mergesibling(rng, cmdName, value) {
            var collapsed = rng.collapsed,
                bk = rng.createBookmark(),
                common;
            if (collapsed) {
                common = bk.start.parentNode;
                while (dtd.$inline[common.tagName]) {
                    common = common.parentNode
                }
            } else {
                common = domUtils.getCommonAncestor(bk.start, bk.end)
            }
            utils.each(domUtils.getElementsByTagName(common, "span"), function(span) {
                if (!span.parentNode || domUtils.isBookmarkNode(span)) {
                    return
                }
                if (/\s*border\s*:\s*none;?\s*/i.test(span.style.cssText)) {
                    if (/^\s*border\s*:\s*none;?\s*$/.test(span.style.cssText)) {
                        domUtils.remove(span, true)
                    } else {
                        domUtils.removeStyle(span, "border")
                    }
                    return
                }
                if (/border/i.test(span.style.cssText) && span.parentNode.tagName == "SPAN" && /border/i.test(span.parentNode.style.cssText)) {
                    span.style.cssText = span.style.cssText.replace(/border[^:]*:[^;]+;?/gi, "")
                }
                if (!(cmdName == "fontborder" && value == "none")) {
                    var next = span.nextSibling;
                    while (next && next.nodeType == 1 && next.tagName == "SPAN") {
                        if (domUtils.isBookmarkNode(next) && cmdName == "fontborder") {
                            span.appendChild(next);
                            next = span.nextSibling;
                            continue
                        }
                        if (next.style.cssText == span.style.cssText) {
                            domUtils.moveChild(next, span);
                            domUtils.remove(next)
                        }
                        if (span.nextSibling === next) {
                            break
                        }
                        next = span.nextSibling
                    }
                }
                mergeWithParent(span);
                if (browser.ie && browser.version > 8) {
                    var parent = domUtils.findParent(span, function(n) {
                        return n.tagName == "SPAN" && /background-color/.test(n.style.cssText)
                    });
                    if (parent && !/background-color/.test(span.style.cssText)) {
                        span.style.backgroundColor = parent.style.backgroundColor
                    }
                }
            });
            rng.moveToBookmark(bk);
            mergeChild(rng, cmdName, value)
        }
        me.addInputRule(function(root) {
            utils.each(root.getNodesByTagName("u s del font strike"), function(node) {
                if (node.tagName == "font") {
                    var cssStyle = [];
                    for (var p in node.attrs) {
                        switch (p) {
                            case "size":
                                cssStyle.push("font-size:" + ({
                                    "1": "10",
                                    "2": "12",
                                    "3": "16",
                                    "4": "18",
                                    "5": "24",
                                    "6": "32",
                                    "7": "48"
                                }[node.attrs[p]] || node.attrs[p]) + "px");
                                break;
                            case "color":
                                cssStyle.push("color:" + node.attrs[p]);
                                break;
                            case "face":
                                cssStyle.push("font-family:" + node.attrs[p]);
                                break;
                            case "style":
                                cssStyle.push(node.attrs[p])
                        }
                    }
                    node.attrs = {
                        "style": cssStyle.join(";")
                    }
                } else {
                    var val = node.tagName == "u" ? "underline" : "line-through";
                    node.attrs = {
                        "style": (node.getAttr("style") || "") + "text-decoration:" + val + ";"
                    }
                }
                node.tagName = "span"
            })
        });
        for (var p in fonts) {
            (function(cmd, style) {
                UE.commands[cmd] = {
                    execCommand: function(cmdName, value) {
                        value = value || (this.queryCommandState(cmdName) ? "none" : cmdName == "underline" ? "underline" : cmdName == "fontborder" ? "1px solid #000" : "line-through");
                        var me = this,
                            range = this.selection.getRange(),
                            text;
                        if (value == "default") {
                            if (range.collapsed) {
                                text = me.document.createTextNode("font");
                                range.insertNode(text).select()
                            }
                            me.execCommand("removeFormat", "span,a", style);
                            if (text) {
                                range.setStartBefore(text).collapse(true);
                                domUtils.remove(text)
                            }
                            mergesibling(range, cmdName, value);
                            range.select()
                        } else {
                            if (!range.collapsed) {
                                if (needCmd[cmd] && me.queryCommandValue(cmd)) {
                                    me.execCommand("removeFormat", "span,a", style)
                                }
                                range = me.selection.getRange();
                                range.applyInlineStyle("span", {
                                    "style": style + ":" + value
                                });
                                mergesibling(range, cmdName, value);
                                range.select()
                            } else {
                                var span = domUtils.findParentByTagName(range.startContainer, "span", true);
                                text = me.document.createTextNode("font");
                                if (span && !span.children.length && !span[browser.ie ? "innerText" : "textContent"].replace(fillCharReg, "").length) {
                                    range.insertNode(text);
                                    if (needCmd[cmd]) {
                                        range.selectNode(text).select();
                                        me.execCommand("removeFormat", "span,a", style, null);
                                        span = domUtils.findParentByTagName(text, "span", true);
                                        range.setStartBefore(text)
                                    }
                                    span && (span.style.cssText += ";" + style + ":" + value);
                                    range.collapse(true).select()
                                } else {
                                    range.insertNode(text);
                                    range.selectNode(text).select();
                                    span = range.document.createElement("span");
                                    if (needCmd[cmd]) {
                                        if (domUtils.findParentByTagName(text, "a", true)) {
                                            range.setStartBefore(text).setCursor();
                                            domUtils.remove(text);
                                            return
                                        }
                                        me.execCommand("removeFormat", "span,a", style)
                                    }
                                    span.style.cssText = style + ":" + value;
                                    text.parentNode.insertBefore(span, text);
                                    if (!browser.ie || browser.ie && browser.version == 9) {
                                        var spanParent = span.parentNode;
                                        while (!domUtils.isBlockElm(spanParent)) {
                                            if (spanParent.tagName == "SPAN") {
                                                span.style.cssText = spanParent.style.cssText + ";" + span.style.cssText
                                            }
                                            spanParent = spanParent.parentNode
                                        }
                                    }
                                    if (opera) {
                                        setTimeout(function() {
                                            range.setStart(span, 0).collapse(true);
                                            mergesibling(range, cmdName, value);
                                            range.select()
                                        })
                                    } else {
                                        range.setStart(span, 0).collapse(true);
                                        mergesibling(range, cmdName, value);
                                        range.select()
                                    }
                                }
                                domUtils.remove(text)
                            }
                        }
                        return true
                    },
                    queryCommandValue: function(cmdName) {
                        var startNode = this.selection.getStart();
                        if (cmdName == "underline" || cmdName == "strikethrough") {
                            var tmpNode = startNode,
                                value;
                            while (tmpNode && !domUtils.isBlockElm(tmpNode) && !domUtils.isBody(tmpNode)) {
                                if (tmpNode.nodeType == 1) {
                                    value = domUtils.getComputedStyle(tmpNode, style);
                                    if (value != "none") {
                                        return value
                                    }
                                }
                                tmpNode = tmpNode.parentNode
                            }
                            return "none"
                        }
                        if (cmdName == "fontborder") {
                            var tmp = startNode,
                                val;
                            while (tmp && dtd.$inline[tmp.tagName]) {
                                if (val = domUtils.getComputedStyle(tmp, "border")) {
                                    if (/1px/.test(val) && /solid/.test(val)) {
                                        return val
                                    }
                                }
                                tmp = tmp.parentNode
                            }
                            return ""
                        }
                        if (cmdName == "FontSize") {
                            var styleVal = domUtils.getComputedStyle(startNode, style),
                                tmp = /^([\d\.]+)(\w+)$/.exec(styleVal);
                            if (tmp) {
                                return Math.floor(tmp[1]) + tmp[2]
                            }
                            return styleVal
                        }
                        return domUtils.getComputedStyle(startNode, style)
                    },
                    queryCommandState: function(cmdName) {
                        if (!needCmd[cmdName]) {
                            return 0
                        }
                        var val = this.queryCommandValue(cmdName);
                        if (cmdName == "fontborder") {
                            return /1px/.test(val) && /solid/.test(val)
                        } else {
                            return cmdName == "underline" ? /underline/.test(val) : /line\-through/.test(val)
                        }
                    }
                }
            })(p, fonts[p])
        }
    };
    UE.plugins["link"] = function() {
        function optimize(range) {
            var start = range.startContainer,
                end = range.endContainer;
            if (start = domUtils.findParentByTagName(start, "a", true)) {
                range.setStartBefore(start)
            }
            if (end = domUtils.findParentByTagName(end, "a", true)) {
                range.setEndAfter(end)
            }
        }
        UE.commands["unlink"] = {
            execCommand: function() {
                var range = this.selection.getRange(),
                    bookmark;
                if (range.collapsed && !domUtils.findParentByTagName(range.startContainer, "a", true)) {
                    return
                }
                bookmark = range.createBookmark();
                optimize(range);
                range.removeInlineStyle("a").moveToBookmark(bookmark).select()
            },
            queryCommandState: function() {
                return !this.highlight && this.queryCommandValue("link") ? 0 : -1
            }
        };

        function doLink(range, opt, me) {
            var rngClone = range.cloneRange(),
                link = me.queryCommandValue("link");
            optimize(range = range.adjustmentBoundary());
            var start = range.startContainer;
            if (start.nodeType == 1 && link) {
                start = start.childNodes[range.startOffset];
                if (start && start.nodeType == 1 && start.tagName == "A" && /^(?:https?|ftp|file)\s*:\s*\/\//.test(start[browser.ie ? "innerText" : "textContent"])) {
                    start[browser.ie ? "innerText" : "textContent"] = utils.html(opt.textValue || opt.href)
                }
            }
            if (!rngClone.collapsed || link) {
                range.removeInlineStyle("a");
                rngClone = range.cloneRange()
            }
            if (rngClone.collapsed) {
                var a = range.document.createElement("a"),
                    text = "";
                if (opt.textValue) {
                    text = utils.html(opt.textValue);
                    delete opt.textValue
                } else {
                    text = utils.html(opt.href)
                }
                domUtils.setAttributes(a, opt);
                start = domUtils.findParentByTagName(rngClone.startContainer, "a", true);
                if (start && domUtils.isInNodeEndBoundary(rngClone, start)) {
                    range.setStartAfter(start).collapse(true)
                }
                a[browser.ie ? "innerText" : "textContent"] = text;
                range.insertNode(a).selectNode(a)
            } else {
                range.applyInlineStyle("a", opt)
            }
        }
        UE.commands["link"] = {
            execCommand: function(cmdName, opt) {
                var range;
                opt._href && (opt._href = utils.unhtml(opt._href, /[<">]/g));
                opt.href && (opt.href = utils.unhtml(opt.href, /[<">]/g));
                opt.textValue && (opt.textValue = utils.unhtml(opt.textValue, /[<">]/g));
                doLink(range = this.selection.getRange(), opt, this);
                range.collapse().select(true)
            },
            queryCommandValue: function() {
                var range = this.selection.getRange(),
                    node;
                if (range.collapsed) {
                    node = range.startContainer;
                    node = node.nodeType == 1 ? node : node.parentNode;
                    if (node && (node = domUtils.findParentByTagName(node, "a", true)) && !domUtils.isInNodeEndBoundary(range, node)) {
                        return node
                    }
                } else {
                    range.shrinkBoundary();
                    var start = range.startContainer.nodeType == 3 || !range.startContainer.childNodes[range.startOffset] ? range.startContainer : range.startContainer.childNodes[range.startOffset],
                        end = range.endContainer.nodeType == 3 || range.endOffset == 0 ? range.endContainer : range.endContainer.childNodes[range.endOffset - 1],
                        common = range.getCommonAncestor();
                    node = domUtils.findParentByTagName(common, "a", true);
                    if (!node && common.nodeType == 1) {
                        var as = common.getElementsByTagName("a"),
                            ps, pe;
                        for (var i = 0, ci; ci = as[i++];) {
                            ps = domUtils.getPosition(ci, start), pe = domUtils.getPosition(ci, end);
                            if ((ps & domUtils.POSITION_FOLLOWING || ps & domUtils.POSITION_CONTAINS) && (pe & domUtils.POSITION_PRECEDING || pe & domUtils.POSITION_CONTAINS)) {
                                node = ci;
                                break
                            }
                        }
                    }
                    return node
                }
            },
            queryCommandState: function() {
                var img = this.selection.getRange().getClosedNode(),
                    flag = img && (img.className == "edui-faked-video" || img.className.indexOf("edui-upload-video") != -1);
                return flag ? -1 : 0
            }
        }
    };
    UE.plugins["insertframe"] = function() {
        var me = this;

        function deleteIframe() {
            me._iframe && delete me._iframe
        }
        me.addListener("selectionchange", function() {
            deleteIframe()
        })
    };
    UE.commands["scrawl"] = {
        queryCommandState: function() {
            return (browser.ie && browser.version <= 8) ? -1 : 0
        }
    };
    UE.plugins["removeformat"] = function() {
        var me = this;
        me.setOpt({
            "removeFormatTags": "b,big,code,del,dfn,em,font,i,ins,kbd,q,samp,small,span,strike,strong,sub,sup,tt,u,var",
            "removeFormatAttributes": "class,style,lang,width,height,align,hspace,valign"
        });
        me.commands["removeformat"] = {
            execCommand: function(cmdName, tags, style, attrs, notIncludeA) {
                var tagReg = new RegExp("^(?:" + (tags || this.options.removeFormatTags).replace(/,/g, "|") + ")$", "i"),
                    removeFormatAttributes = style ? [] : (attrs || this.options.removeFormatAttributes).split(","),
                    range = new dom.Range(this.document),
                    bookmark, node, parent, filter = function(node) {
                        return node.nodeType == 1
                    };

                function isRedundantSpan(node) {
                    if (node.nodeType == 3 || node.tagName.toLowerCase() != "span") {
                        return 0
                    }
                    if (browser.ie) {
                        var attrs = node.attributes;
                        if (attrs.length) {
                            for (var i = 0, l = attrs.length; i < l; i++) {
                                if (attrs[i].specified) {
                                    return 0
                                }
                            }
                            return 1
                        }
                    }
                    return !node.attributes.length
                }
                function doRemove(range) {
                    var bookmark1 = range.createBookmark();
                    if (range.collapsed) {
                        range.enlarge(true)
                    }
                    if (!notIncludeA) {
                        var aNode = domUtils.findParentByTagName(range.startContainer, "a", true);
                        if (aNode) {
                            range.setStartBefore(aNode)
                        }
                        aNode = domUtils.findParentByTagName(range.endContainer, "a", true);
                        if (aNode) {
                            range.setEndAfter(aNode)
                        }
                    }
                    bookmark = range.createBookmark();
                    node = bookmark.start;
                    while ((parent = node.parentNode) && !domUtils.isBlockElm(parent)) {
                        domUtils.breakParent(node, parent);
                        domUtils.clearEmptySibling(node)
                    }
                    if (bookmark.end) {
                        node = bookmark.end;
                        while ((parent = node.parentNode) && !domUtils.isBlockElm(parent)) {
                            domUtils.breakParent(node, parent);
                            domUtils.clearEmptySibling(node)
                        }
                        var current = domUtils.getNextDomNode(bookmark.start, false, filter),
                            next;
                        while (current) {
                            if (current == bookmark.end) {
                                break
                            }
                            next = domUtils.getNextDomNode(current, true, filter);
                            if (!dtd.$empty[current.tagName.toLowerCase()] && !domUtils.isBookmarkNode(current)) {
                                if (tagReg.test(current.tagName)) {
                                    if (style) {
                                        domUtils.removeStyle(current, style);
                                        if (isRedundantSpan(current) && style != "text-decoration") {
                                            domUtils.remove(current, true)
                                        }
                                    } else {
                                        domUtils.remove(current, true)
                                    }
                                } else {
                                    if (!dtd.$tableContent[current.tagName] && !dtd.$list[current.tagName]) {
                                        domUtils.removeAttributes(current, removeFormatAttributes);
                                        if (isRedundantSpan(current)) {
                                            domUtils.remove(current, true)
                                        }
                                    }
                                }
                            }
                            current = next
                        }
                    }
                    var pN = bookmark.start.parentNode;
                    if (domUtils.isBlockElm(pN) && !dtd.$tableContent[pN.tagName] && !dtd.$list[pN.tagName]) {
                        domUtils.removeAttributes(pN, removeFormatAttributes)
                    }
                    pN = bookmark.end.parentNode;
                    if (bookmark.end && domUtils.isBlockElm(pN) && !dtd.$tableContent[pN.tagName] && !dtd.$list[pN.tagName]) {
                        domUtils.removeAttributes(pN, removeFormatAttributes)
                    }
                    range.moveToBookmark(bookmark).moveToBookmark(bookmark1);
                    var node = range.startContainer,
                        tmp, collapsed = range.collapsed;
                    while (node.nodeType == 1 && domUtils.isEmptyNode(node) && dtd.$removeEmpty[node.tagName]) {
                        tmp = node.parentNode;
                        range.setStartBefore(node);
                        if (range.startContainer === range.endContainer) {
                            range.endOffset--
                        }
                        domUtils.remove(node);
                        node = tmp
                    }
                    if (!collapsed) {
                        node = range.endContainer;
                        while (node.nodeType == 1 && domUtils.isEmptyNode(node) && dtd.$removeEmpty[node.tagName]) {
                            tmp = node.parentNode;
                            range.setEndBefore(node);
                            domUtils.remove(node);
                            node = tmp
                        }
                    }
                }
                range = this.selection.getRange();
                doRemove(range);
                range.select()
            }
        }
    };
    UE.plugins["blockquote"] = function() {
        var me = this;

        function getObj(editor) {
            return domUtils.filterNodeList(editor.selection.getStartElementPath(), "blockquote")
        }
        me.commands["blockquote"] = {
            execCommand: function(cmdName, attrs) {
                var range = this.selection.getRange(),
                    obj = getObj(this),
                    blockquote = dtd.blockquote,
                    bookmark = range.createBookmark();
                if (obj) {
                    var start = range.startContainer,
                        startBlock = domUtils.isBlockElm(start) ? start : domUtils.findParent(start, function(node) {
                            return domUtils.isBlockElm(node)
                        }),
                        end = range.endContainer,
                        endBlock = domUtils.isBlockElm(end) ? end : domUtils.findParent(end, function(node) {
                            return domUtils.isBlockElm(node)
                        });
                    startBlock = domUtils.findParentByTagName(startBlock, "li", true) || startBlock;
                    endBlock = domUtils.findParentByTagName(endBlock, "li", true) || endBlock;
                    if (startBlock.tagName == "LI" || startBlock.tagName == "TD" || startBlock === obj || domUtils.isBody(startBlock)) {
                        domUtils.remove(obj, true)
                    } else {
                        domUtils.breakParent(startBlock, obj)
                    }
                    if (startBlock !== endBlock) {
                        obj = domUtils.findParentByTagName(endBlock, "blockquote");
                        if (obj) {
                            if (endBlock.tagName == "LI" || endBlock.tagName == "TD" || domUtils.isBody(endBlock)) {
                                obj.parentNode && domUtils.remove(obj, true)
                            } else {
                                domUtils.breakParent(endBlock, obj)
                            }
                        }
                    }
                    var blockquotes = domUtils.getElementsByTagName(this.document, "blockquote");
                    for (var i = 0, bi; bi = blockquotes[i++];) {
                        if (!bi.childNodes.length) {
                            domUtils.remove(bi)
                        } else {
                            if (domUtils.getPosition(bi, startBlock) & domUtils.POSITION_FOLLOWING && domUtils.getPosition(bi, endBlock) & domUtils.POSITION_PRECEDING) {
                                domUtils.remove(bi, true)
                            }
                        }
                    }
                } else {
                    var tmpRange = range.cloneRange(),
                        node = tmpRange.startContainer.nodeType == 1 ? tmpRange.startContainer : tmpRange.startContainer.parentNode,
                        preNode = node,
                        doEnd = 1;
                    while (1) {
                        if (domUtils.isBody(node)) {
                            if (preNode !== node) {
                                if (range.collapsed) {
                                    tmpRange.selectNode(preNode);
                                    doEnd = 0
                                } else {
                                    tmpRange.setStartBefore(preNode)
                                }
                            } else {
                                tmpRange.setStart(node, 0)
                            }
                            break
                        }
                        if (!blockquote[node.tagName]) {
                            if (range.collapsed) {
                                tmpRange.selectNode(preNode)
                            } else {
                                tmpRange.setStartBefore(preNode)
                            }
                            break
                        }
                        preNode = node;
                        node = node.parentNode
                    }
                    if (doEnd) {
                        preNode = node = node = tmpRange.endContainer.nodeType == 1 ? tmpRange.endContainer : tmpRange.endContainer.parentNode;
                        while (1) {
                            if (domUtils.isBody(node)) {
                                if (preNode !== node) {
                                    tmpRange.setEndAfter(preNode)
                                } else {
                                    tmpRange.setEnd(node, node.childNodes.length)
                                }
                                break
                            }
                            if (!blockquote[node.tagName]) {
                                tmpRange.setEndAfter(preNode);
                                break
                            }
                            preNode = node;
                            node = node.parentNode
                        }
                    }
                    node = range.document.createElement("blockquote");
                    domUtils.setAttributes(node, attrs);
                    node.appendChild(tmpRange.extractContents());
                    tmpRange.insertNode(node);
                    var childs = domUtils.getElementsByTagName(node, "blockquote");
                    for (var i = 0, ci; ci = childs[i++];) {
                        if (ci.parentNode) {
                            domUtils.remove(ci, true)
                        }
                    }
                }
                range.moveToBookmark(bookmark).select()
            },
            queryCommandState: function() {
                return getObj(this) ? 1 : 0
            }
        }
    };
    UE.commands["touppercase"] = UE.commands["tolowercase"] = {
        execCommand: function(cmd) {
            var me = this;
            var rng = me.selection.getRange();
            if (rng.collapsed) {
                return rng
            }
            var bk = rng.createBookmark(),
                bkEnd = bk.end,
                filterFn = function(node) {
                    return !domUtils.isBr(node) && !domUtils.isWhitespace(node)
                },
                curNode = domUtils.getNextDomNode(bk.start, false, filterFn);
            while (curNode && (domUtils.getPosition(curNode, bkEnd) & domUtils.POSITION_PRECEDING)) {
                if (curNode.nodeType == 3) {
                    curNode.nodeValue = curNode.nodeValue[cmd == "touppercase" ? "toUpperCase" : "toLowerCase"]()
                }
                curNode = domUtils.getNextDomNode(curNode, true, filterFn);
                if (curNode === bkEnd) {
                    break
                }
            }
            rng.moveToBookmark(bk).select()
        }
    };
    UE.commands["indent"] = {
        execCommand: function() {
            var me = this,
                value = me.queryCommandState("indent") ? "0em" : (me.options.indentValue || "2em");
            me.execCommand("Paragraph", "p", {
                style: "text-indent:" + value
            })
        },
        queryCommandState: function() {
            var pN = domUtils.filterNodeList(this.selection.getStartElementPath(), "p h1 h2 h3 h4 h5 h6");
            return pN && pN.style.textIndent && parseInt(pN.style.textIndent) ? 1 : 0
        }
    };
    UE.commands["print"] = {
        execCommand: function() {
            this.window.print()
        },
        notNeedUndo: 1
    };
    UE.commands["preview"] = {
        execCommand: function() {
            var w = window.open("", "_blank", ""),
                d = w.document;
            d.open();
            d.write('<!DOCTYPE html><html><head><meta charset="utf-8"/><script src="' + this.options.UEDITOR_HOME_URL + 'ueditor.parse.js"><\/script><script>' + "setTimeout(function(){uParse('div',{rootPath: '" + this.options.UEDITOR_HOME_URL + "'})},300)" + "<\/script></head><body><div>" + this.getContent(null, null, true) + "</div></body></html>");
            d.close()
        },
        notNeedUndo: 1
    };
    UE.plugins["selectall"] = function() {
        var me = this;
        me.commands["selectall"] = {
            execCommand: function() {
                var me = this,
                    body = me.body,
                    range = me.selection.getRange();
                range.selectNodeContents(body);
                if (domUtils.isEmptyBlock(body)) {
                    if (browser.opera && body.firstChild && body.firstChild.nodeType == 1) {
                        range.setStartAtFirst(body.firstChild)
                    }
                    range.collapse(true)
                }
                range.select(true)
            },
            notNeedUndo: 1
        };
        me.addshortcutkey({
            "selectAll": "ctrl+65"
        })
    };
    UE.plugins["paragraph"] = function() {
        var me = this,
            block = domUtils.isBlockElm,
            notExchange = ["TD", "LI", "PRE"],
            doParagraph = function(range, style, attrs, sourceCmdName) {
                var bookmark = range.createBookmark(),
                    filterFn = function(node) {
                        return node.nodeType == 1 ? node.tagName.toLowerCase() != "br" && !domUtils.isBookmarkNode(node) : !domUtils.isWhitespace(node)
                    },
                    para;
                range.enlarge(true);
                var bookmark2 = range.createBookmark(),
                    current = domUtils.getNextDomNode(bookmark2.start, false, filterFn),
                    tmpRange = range.cloneRange(),
                    tmpNode;
                while (current && !(domUtils.getPosition(current, bookmark2.end) & domUtils.POSITION_FOLLOWING)) {
                    if (current.nodeType == 3 || !block(current)) {
                        tmpRange.setStartBefore(current);
                        while (current && current !== bookmark2.end && !block(current)) {
                            tmpNode = current;
                            current = domUtils.getNextDomNode(current, false, null, function(node) {
                                return !block(node)
                            })
                        }
                        tmpRange.setEndAfter(tmpNode);
                        para = range.document.createElement(style);
                        if (attrs) {
                            domUtils.setAttributes(para, attrs);
                            if (sourceCmdName && sourceCmdName == "customstyle" && attrs.style) {
                                para.style.cssText = attrs.style
                            }
                        }
                        para.appendChild(tmpRange.extractContents());
                        if (domUtils.isEmptyNode(para)) {
                            domUtils.fillChar(range.document, para)
                        }
                        tmpRange.insertNode(para);
                        var parent = para.parentNode;
                        if (block(parent) && !domUtils.isBody(para.parentNode) && utils.indexOf(notExchange, parent.tagName) == -1) {
                            if (!(sourceCmdName && sourceCmdName == "customstyle")) {
                                parent.getAttribute("dir") && para.setAttribute("dir", parent.getAttribute("dir"));
                                parent.style.cssText && (para.style.cssText = parent.style.cssText + ";" + para.style.cssText);
                                parent.style.textAlign && !para.style.textAlign && (para.style.textAlign = parent.style.textAlign);
                                parent.style.textIndent && !para.style.textIndent && (para.style.textIndent = parent.style.textIndent);
                                parent.style.padding && !para.style.padding && (para.style.padding = parent.style.padding)
                            }
                            if (attrs && /h\d/i.test(parent.tagName) && !/h\d/i.test(para.tagName)) {
                                domUtils.setAttributes(parent, attrs);
                                if (sourceCmdName && sourceCmdName == "customstyle" && attrs.style) {
                                    parent.style.cssText = attrs.style
                                }
                                domUtils.remove(para, true);
                                para = parent
                            } else {
                                domUtils.remove(para.parentNode, true)
                            }
                        }
                        if (utils.indexOf(notExchange, parent.tagName) != -1) {
                            current = parent
                        } else {
                            current = para
                        }
                        current = domUtils.getNextDomNode(current, false, filterFn)
                    } else {
                        current = domUtils.getNextDomNode(current, true, filterFn)
                    }
                }
                return range.moveToBookmark(bookmark2).moveToBookmark(bookmark)
            };
        me.setOpt("paragraph", {
            "p": "",
            "h1": "",
            "h2": "",
            "h3": "",
            "h4": "",
            "h5": "",
            "h6": ""
        });
        me.commands["paragraph"] = {
            execCommand: function(cmdName, style, attrs, sourceCmdName) {
                var range = this.selection.getRange();
                if (range.collapsed) {
                    var txt = this.document.createTextNode("p");
                    range.insertNode(txt);
                    if (browser.ie) {
                        var node = txt.previousSibling;
                        if (node && domUtils.isWhitespace(node)) {
                            domUtils.remove(node)
                        }
                        node = txt.nextSibling;
                        if (node && domUtils.isWhitespace(node)) {
                            domUtils.remove(node)
                        }
                    }
                }
                range = doParagraph(range, style, attrs, sourceCmdName);
                if (txt) {
                    range.setStartBefore(txt).collapse(true);
                    pN = txt.parentNode;
                    domUtils.remove(txt);
                    if (domUtils.isBlockElm(pN) && domUtils.isEmptyNode(pN)) {
                        domUtils.fillNode(this.document, pN)
                    }
                }
                if (browser.gecko && range.collapsed && range.startContainer.nodeType == 1) {
                    var child = range.startContainer.childNodes[range.startOffset];
                    if (child && child.nodeType == 1 && child.tagName.toLowerCase() == style) {
                        range.setStart(child, 0).collapse(true)
                    }
                }
                range.select();
                return true
            },
            queryCommandValue: function() {
                var node = domUtils.filterNodeList(this.selection.getStartElementPath(), "p h1 h2 h3 h4 h5 h6");
                return node ? node.tagName.toLowerCase() : ""
            }
        }
    };
    (function() {
        var block = domUtils.isBlockElm,
            getObj = function(editor) {
                return domUtils.filterNodeList(editor.selection.getStartElementPath(), function(n) {
                    return n && n.nodeType == 1 && n.getAttribute("dir")
                })
            },
            doDirectionality = function(range, editor, forward) {
                var bookmark, filterFn = function(node) {
                        return node.nodeType == 1 ? !domUtils.isBookmarkNode(node) : !domUtils.isWhitespace(node)
                    },
                    obj = getObj(editor);
                if (obj && range.collapsed) {
                    obj.setAttribute("dir", forward);
                    return range
                }
                bookmark = range.createBookmark();
                range.enlarge(true);
                var bookmark2 = range.createBookmark(),
                    current = domUtils.getNextDomNode(bookmark2.start, false, filterFn),
                    tmpRange = range.cloneRange(),
                    tmpNode;
                while (current && !(domUtils.getPosition(current, bookmark2.end) & domUtils.POSITION_FOLLOWING)) {
                    if (current.nodeType == 3 || !block(current)) {
                        tmpRange.setStartBefore(current);
                        while (current && current !== bookmark2.end && !block(current)) {
                            tmpNode = current;
                            current = domUtils.getNextDomNode(current, false, null, function(node) {
                                return !block(node)
                            })
                        }
                        tmpRange.setEndAfter(tmpNode);
                        var common = tmpRange.getCommonAncestor();
                        if (!domUtils.isBody(common) && block(common)) {
                            common.setAttribute("dir", forward);
                            current = common
                        } else {
                            var p = range.document.createElement("p");
                            p.setAttribute("dir", forward);
                            var frag = tmpRange.extractContents();
                            p.appendChild(frag);
                            tmpRange.insertNode(p);
                            current = p
                        }
                        current = domUtils.getNextDomNode(current, false, filterFn)
                    } else {
                        current = domUtils.getNextDomNode(current, true, filterFn)
                    }
                }
                return range.moveToBookmark(bookmark2).moveToBookmark(bookmark)
            };
        UE.commands["directionality"] = {
            execCommand: function(cmdName, forward) {
                var range = this.selection.getRange();
                if (range.collapsed) {
                    var txt = this.document.createTextNode("d");
                    range.insertNode(txt)
                }
                doDirectionality(range, this, forward);
                if (txt) {
                    range.setStartBefore(txt).collapse(true);
                    domUtils.remove(txt)
                }
                range.select();
                return true
            },
            queryCommandValue: function() {
                var node = getObj(this);
                return node ? node.getAttribute("dir") : "ltr"
            }
        }
    })();
    UE.plugins["horizontal"] = function() {
        var me = this;
        me.commands["horizontal"] = {
            execCommand: function(cmdName) {
                var me = this;
                if (me.queryCommandState(cmdName) !== -1) {
                    me.execCommand("insertHtml", "<hr>");
                    var range = me.selection.getRange(),
                        start = range.startContainer;
                    if (start.nodeType == 1 && !start.childNodes[range.startOffset]) {
                        var tmp;
                        if (tmp = start.childNodes[range.startOffset - 1]) {
                            if (tmp.nodeType == 1 && tmp.tagName == "HR") {
                                if (me.options.enterTag == "p") {
                                    tmp = me.document.createElement("p");
                                    range.insertNode(tmp);
                                    range.setStart(tmp, 0).setCursor()
                                } else {
                                    tmp = me.document.createElement("br");
                                    range.insertNode(tmp);
                                    range.setStartBefore(tmp).setCursor()
                                }
                            }
                        }
                    }
                    return true
                }
            },
            queryCommandState: function() {
                return domUtils.filterNodeList(this.selection.getStartElementPath(), "table") ? -1 : 0
            }
        };
        me.addListener("delkeydown", function(name, evt) {
            var rng = this.selection.getRange();
            rng.txtToElmBoundary(true);
            if (domUtils.isStartInblock(rng)) {
                var tmpNode = rng.startContainer;
                var pre = tmpNode.previousSibling;
                if (pre && domUtils.isTagNode(pre, "hr")) {
                    domUtils.remove(pre);
                    rng.select();
                    domUtils.preventDefault(evt);
                    return true
                }
            }
        })
    };
    UE.commands["time"] = UE.commands["date"] = {
        execCommand: function(cmd, format) {
            var date = new Date;

            function formatTime(date, format) {
                var hh = ("0" + date.getHours()).slice(-2),
                    ii = ("0" + date.getMinutes()).slice(-2),
                    ss = ("0" + date.getSeconds()).slice(-2);
                format = format || "hh:ii:ss";
                return format.replace(/hh/ig, hh).replace(/ii/ig, ii).replace(/ss/ig, ss)
            }
            function formatDate(date, format) {
                var yyyy = ("000" + date.getFullYear()).slice(-4),
                    yy = yyyy.slice(-2),
                    mm = ("0" + (date.getMonth() + 1)).slice(-2),
                    dd = ("0" + date.getDate()).slice(-2);
                format = format || "yyyy-mm-dd";
                return format.replace(/yyyy/ig, yyyy).replace(/yy/ig, yy).replace(/mm/ig, mm).replace(/dd/ig, dd)
            }
            this.execCommand("insertHtml", cmd == "time" ? formatTime(date, format) : formatDate(date, format))
        }
    };
    UE.plugins["rowspacing"] = function() {
        var me = this;
        me.setOpt({
            "rowspacingtop": ["5", "10", "15", "20", "25"],
            "rowspacingbottom": ["5", "10", "15", "20", "25"]
        });
        me.commands["rowspacing"] = {
            execCommand: function(cmdName, value, dir) {
                this.execCommand("paragraph", "p", {
                    style: "margin-" + dir + ":" + value + "px"
                });
                return true
            },
            queryCommandValue: function(cmdName, dir) {
                var pN = domUtils.filterNodeList(this.selection.getStartElementPath(), function(node) {
                        return domUtils.isBlockElm(node)
                    }),
                    value;
                if (pN) {
                    value = domUtils.getComputedStyle(pN, "margin-" + dir).replace(/[^\d]/g, "");
                    return !value ? 0 : value
                }
                return 0
            }
        }
    };
    UE.plugins["lineheight"] = function() {
        var me = this;
        me.setOpt({
            "lineheight": ["1", "1.5", "1.75", "2", "3", "4", "5"]
        });
        me.commands["lineheight"] = {
            execCommand: function(cmdName, value) {
                this.execCommand("paragraph", "p", {
                    style: "line-height:" + (value == "1" ? "normal" : value + "em")
                });
                return true
            },
            queryCommandValue: function() {
                var pN = domUtils.filterNodeList(this.selection.getStartElementPath(), function(node) {
                    return domUtils.isBlockElm(node)
                });
                if (pN) {
                    var value = domUtils.getComputedStyle(pN, "line-height");
                    return value == "normal" ? 1 : value.replace(/[^\d.]*/ig, "")
                }
            }
        }
    };
    UE.plugins["insertcode"] = function() {
        var me = this;
        me.ready(function() {
            utils.cssRule("pre", "pre{margin:.5em 0;padding:.4em .6em;border-radius:8px;background:#f8f8f8;}", me.document)
        });
        me.setOpt("insertcode", {
            "as3": "ActionScript3",
            "bash": "Bash/Shell",
            "cpp": "C/C++",
            "css": "Css",
            "cf": "CodeFunction",
            "c#": "C#",
            "delphi": "Delphi",
            "diff": "Diff",
            "erlang": "Erlang",
            "groovy": "Groovy",
            "html": "Html",
            "java": "Java",
            "jfx": "JavaFx",
            "js": "Javascript",
            "pl": "Perl",
            "php": "Php",
            "plain": "Plain Text",
            "ps": "PowerShell",
            "python": "Python",
            "ruby": "Ruby",
            "scala": "Scala",
            "sql": "Sql",
            "vb": "Vb",
            "xml": "Xml"
        });
        me.commands["insertcode"] = {
            execCommand: function(cmd, lang) {
                var me = this,
                    rng = me.selection.getRange(),
                    pre = domUtils.findParentByTagName(rng.startContainer, "pre", true);
                if (pre) {
                    pre.className = "brush:" + lang + ";toolbar:false;"
                } else {
                    var code = "";
                    if (rng.collapsed) {
                        code = browser.ie && browser.ie11below ? (browser.version <= 8 ? "&nbsp;" : "") : "<br/>"
                    } else {
                        var frag = rng.extractContents();
                        var div = me.document.createElement("div");
                        div.appendChild(frag);
                        utils.each(UE.filterNode(UE.htmlparser(div.innerHTML.replace(/[\r\t]/g, "")), me.options.filterTxtRules).children, function(node) {
                            if (browser.ie && browser.ie11below && browser.version > 8) {
                                if (node.type == "element") {
                                    if (node.tagName == "br") {
                                        code += "\n"
                                    } else {
                                        if (!dtd.$empty[node.tagName]) {
                                            utils.each(node.children, function(cn) {
                                                if (cn.type == "element") {
                                                    if (cn.tagName == "br") {
                                                        code += "\n"
                                                    } else {
                                                        if (!dtd.$empty[node.tagName]) {
                                                            code += cn.innerText()
                                                        }
                                                    }
                                                } else {
                                                    code += cn.data
                                                }
                                            });
                                            if (!/\n$/.test(code)) {
                                                code += "\n"
                                            }
                                        }
                                    }
                                } else {
                                    code += node.data + "\n"
                                }
                                if (!node.nextSibling() && /\n$/.test(code)) {
                                    code = code.replace(/\n$/, "")
                                }
                            } else {
                                if (browser.ie && browser.ie11below) {
                                    if (node.type == "element") {
                                        if (node.tagName == "br") {
                                            code += "<br>"
                                        } else {
                                            if (!dtd.$empty[node.tagName]) {
                                                utils.each(node.children, function(cn) {
                                                    if (cn.type == "element") {
                                                        if (cn.tagName == "br") {
                                                            code += "<br>"
                                                        } else {
                                                            if (!dtd.$empty[node.tagName]) {
                                                                code += cn.innerText()
                                                            }
                                                        }
                                                    } else {
                                                        code += cn.data
                                                    }
                                                });
                                                if (!/br>$/.test(code)) {
                                                    code += "<br>"
                                                }
                                            }
                                        }
                                    } else {
                                        code += node.data + "<br>"
                                    }
                                    if (!node.nextSibling() && /<br>$/.test(code)) {
                                        code = code.replace(/<br>$/, "")
                                    }
                                } else {
                                    code += (node.type == "element" ? (dtd.$empty[node.tagName] ? "" : node.innerText()) : node.data);
                                    if (!/br\/?\s*>$/.test(code)) {
                                        if (!node.nextSibling()) {
                                            return
                                        }
                                        code += "<br>"
                                    }
                                }
                            }
                        })
                    }
                    me.execCommand("inserthtml", '<pre id="coder"class="brush:' + lang + ';toolbar:false">' + code + "</pre>", true);
                    pre = me.document.getElementById("coder");
                    domUtils.removeAttributes(pre, "id");
                    var tmpNode = pre.previousSibling;
                    if (tmpNode && (tmpNode.nodeType == 3 && tmpNode.nodeValue.length == 1 && browser.ie && browser.version == 6 || domUtils.isEmptyBlock(tmpNode))) {
                        domUtils.remove(tmpNode)
                    }
                    var rng = me.selection.getRange();
                    if (domUtils.isEmptyBlock(pre)) {
                        rng.setStart(pre, 0).setCursor(false, true)
                    } else {
                        rng.selectNodeContents(pre).select()
                    }
                }
            },
            queryCommandValue: function() {
                var path = this.selection.getStartElementPath();
                var lang = "";
                utils.each(path, function(node) {
                    if (node.nodeName == "PRE") {
                        var match = node.className.match(/brush:([^;]+)/);
                        lang = match && match[1] ? match[1] : "";
                        return false
                    }
                });
                return lang
            }
        };
        me.addInputRule(function(root) {
            utils.each(root.getNodesByTagName("pre"), function(pre) {
                var brs = pre.getNodesByTagName("br");
                if (brs.length) {
                    browser.ie && browser.ie11below && browser.version > 8 && utils.each(brs, function(br) {
                        var txt = UE.uNode.createText("\n");
                        br.parentNode.insertBefore(txt, br);
                        br.parentNode.removeChild(br)
                    });
                    return
                }
                if (browser.ie && browser.ie11below && browser.version > 8) {
                    return
                }
                var code = pre.innerText().split(/\n/);
                pre.innerHTML("");
                utils.each(code, function(c) {
                    if (c.length) {
                        pre.appendChild(UE.uNode.createText(c))
                    }
                    pre.appendChild(UE.uNode.createElement("br"))
                })
            })
        });
        me.addOutputRule(function(root) {
            utils.each(root.getNodesByTagName("pre"), function(pre) {
                var code = "";
                utils.each(pre.children, function(n) {
                    if (n.type == "text") {
                        code += n.data.replace(/[ ]/g, "&nbsp;").replace(/\n$/, "")
                    } else {
                        if (n.tagName == "br") {
                            code += "\n"
                        } else {
                            code += (!dtd.$empty[n.tagName] ? "" : n.innerText())
                        }
                    }
                });
                pre.innerText(code.replace(/(&nbsp;|\n)+$/, ""))
            })
        });
        me.notNeedCodeQuery = {
            help: 1,
            undo: 1,
            redo: 1,
            source: 1,
            print: 1,
            searchreplace: 1,
            fullscreen: 1,
            preview: 1,
            insertparagraph: 1,
            elementpath: 1,
            insertcode: 1,
            inserthtml: 1,
            selectall: 1
        };
        var orgQuery = me.queryCommandState;
        me.queryCommandState = function(cmd) {
            var me = this;
            if (!me.notNeedCodeQuery[cmd.toLowerCase()] && me.selection && me.queryCommandValue("insertcode")) {
                return -1
            }
            return UE.Editor.prototype.queryCommandState.apply(this, arguments)
        };
        me.addListener("beforeenterkeydown", function() {
            var rng = me.selection.getRange();
            var pre = domUtils.findParentByTagName(rng.startContainer, "pre", true);
            if (pre) {
                me.fireEvent("saveScene");
                if (!rng.collapsed) {
                    rng.deleteContents()
                }
                if (!browser.ie || browser.ie9above) {
                    var tmpNode = me.document.createElement("br"),
                        pre;
                    rng.insertNode(tmpNode).setStartAfter(tmpNode).collapse(true);
                    var next = tmpNode.nextSibling;
                    if (!next && (!browser.ie || browser.version > 10)) {
                        rng.insertNode(tmpNode.cloneNode(false))
                    } else {
                        rng.setStartAfter(tmpNode)
                    }
                    pre = tmpNode.previousSibling;
                    var tmp;
                    while (pre) {
                        tmp = pre;
                        pre = pre.previousSibling;
                        if (!pre || pre.nodeName == "BR") {
                            pre = tmp;
                            break
                        }
                    }
                    if (pre) {
                        var str = "";
                        while (pre && pre.nodeName != "BR" && new RegExp("^[\\s" + domUtils.fillChar + "]*$").test(pre.nodeValue)) {
                            str += pre.nodeValue;
                            pre = pre.nextSibling
                        }
                        if (pre.nodeName != "BR") {
                            var match = pre.nodeValue.match(new RegExp("^([\\s" + domUtils.fillChar + "]+)"));
                            if (match && match[1]) {
                                str += match[1]
                            }
                        }
                        if (str) {
                            str = me.document.createTextNode(str);
                            rng.insertNode(str).setStartAfter(str)
                        }
                    }
                    rng.collapse(true).select(true)
                } else {
                    if (browser.version > 8) {
                        var txt = me.document.createTextNode("\n");
                        var start = rng.startContainer;
                        if (rng.startOffset == 0) {
                            var preNode = start.previousSibling;
                            if (preNode) {
                                rng.insertNode(txt);
                                var fillchar = me.document.createTextNode(" ");
                                rng.setStartAfter(txt).insertNode(fillchar).setStart(fillchar, 0).collapse(true).select(true)
                            }
                        } else {
                            rng.insertNode(txt).setStartAfter(txt);
                            var fillchar = me.document.createTextNode(" ");
                            start = rng.startContainer.childNodes[rng.startOffset];
                            if (start && !/^\n/.test(start.nodeValue)) {
                                rng.setStartBefore(txt)
                            }
                            rng.insertNode(fillchar).setStart(fillchar, 0).collapse(true).select(true)
                        }
                    } else {
                        var tmpNode = me.document.createElement("br");
                        rng.insertNode(tmpNode);
                        rng.insertNode(me.document.createTextNode(domUtils.fillChar));
                        rng.setStartAfter(tmpNode);
                        pre = tmpNode.previousSibling;
                        var tmp;
                        while (pre) {
                            tmp = pre;
                            pre = pre.previousSibling;
                            if (!pre || pre.nodeName == "BR") {
                                pre = tmp;
                                break
                            }
                        }
                        if (pre) {
                            var str = "";
                            while (pre && pre.nodeName != "BR" && new RegExp("^[ " + domUtils.fillChar + "]*$").test(pre.nodeValue)) {
                                str += pre.nodeValue;
                                pre = pre.nextSibling
                            }
                            if (pre.nodeName != "BR") {
                                var match = pre.nodeValue.match(new RegExp("^([ " + domUtils.fillChar + "]+)"));
                                if (match && match[1]) {
                                    str += match[1]
                                }
                            }
                            str = me.document.createTextNode(str);
                            rng.insertNode(str).setStartAfter(str)
                        }
                        rng.collapse(true).select()
                    }
                }
                me.fireEvent("saveScene");
                return true
            }
        });
        me.addListener("tabkeydown", function(cmd, evt) {
            var rng = me.selection.getRange();
            var pre = domUtils.findParentByTagName(rng.startContainer, "pre", true);
            if (pre) {
                me.fireEvent("saveScene");
                if (evt.shiftKey) {} else {
                    if (!rng.collapsed) {
                        var bk = rng.createBookmark();
                        var start = bk.start.previousSibling;
                        while (start) {
                            if (pre.firstChild === start && !domUtils.isBr(start)) {
                                pre.insertBefore(me.document.createTextNode("    "), start);
                                break
                            }
                            if (domUtils.isBr(start)) {
                                pre.insertBefore(me.document.createTextNode("    "), start.nextSibling);
                                break
                            }
                            start = start.previousSibling
                        }
                        var end = bk.end;
                        start = bk.start.nextSibling;
                        if (pre.firstChild === bk.start) {
                            pre.insertBefore(me.document.createTextNode("    "), start.nextSibling)
                        }
                        while (start && start !== end) {
                            if (domUtils.isBr(start) && start.nextSibling) {
                                if (start.nextSibling === end) {
                                    break
                                }
                                pre.insertBefore(me.document.createTextNode("    "), start.nextSibling)
                            }
                            start = start.nextSibling
                        }
                        rng.moveToBookmark(bk).select()
                    } else {
                        var tmpNode = me.document.createTextNode("    ");
                        rng.insertNode(tmpNode).setStartAfter(tmpNode).collapse(true).select(true)
                    }
                }
                me.fireEvent("saveScene");
                return true
            }
        });
        me.addListener("beforeinserthtml", function(evtName, html) {
            var me = this,
                rng = me.selection.getRange(),
                pre = domUtils.findParentByTagName(rng.startContainer, "pre", true);
            if (pre) {
                if (!rng.collapsed) {
                    rng.deleteContents()
                }
                var htmlstr = "";
                if (browser.ie && browser.version > 8) {
                    utils.each(UE.filterNode(UE.htmlparser(html), me.options.filterTxtRules).children, function(node) {
                        if (node.type == "element") {
                            if (node.tagName == "br") {
                                htmlstr += "\n"
                            } else {
                                if (!dtd.$empty[node.tagName]) {
                                    utils.each(node.children, function(cn) {
                                        if (cn.type == "element") {
                                            if (cn.tagName == "br") {
                                                htmlstr += "\n"
                                            } else {
                                                if (!dtd.$empty[node.tagName]) {
                                                    htmlstr += cn.innerText()
                                                }
                                            }
                                        } else {
                                            htmlstr += cn.data
                                        }
                                    });
                                    if (!/\n$/.test(htmlstr)) {
                                        htmlstr += "\n"
                                    }
                                }
                            }
                        } else {
                            htmlstr += node.data + "\n"
                        }
                        if (!node.nextSibling() && /\n$/.test(htmlstr)) {
                            htmlstr = htmlstr.replace(/\n$/, "")
                        }
                    });
                    var tmpNode = me.document.createTextNode(utils.html(htmlstr.replace(/&nbsp;/g, " ")));
                    rng.insertNode(tmpNode).selectNode(tmpNode).select()
                } else {
                    var frag = me.document.createDocumentFragment();
                    utils.each(UE.filterNode(UE.htmlparser(html), me.options.filterTxtRules).children, function(node) {
                        if (node.type == "element") {
                            if (node.tagName == "br") {
                                frag.appendChild(me.document.createElement("br"))
                            } else {
                                if (!dtd.$empty[node.tagName]) {
                                    utils.each(node.children, function(cn) {
                                        if (cn.type == "element") {
                                            if (cn.tagName == "br") {
                                                frag.appendChild(me.document.createElement("br"))
                                            } else {
                                                if (!dtd.$empty[node.tagName]) {
                                                    frag.appendChild(me.document.createTextNode(utils.html(cn.innerText().replace(/&nbsp;/g, " "))))
                                                }
                                            }
                                        } else {
                                            frag.appendChild(me.document.createTextNode(utils.html(cn.data.replace(/&nbsp;/g, " "))))
                                        }
                                    });
                                    if (frag.lastChild.nodeName != "BR") {
                                        frag.appendChild(me.document.createElement("br"))
                                    }
                                }
                            }
                        } else {
                            frag.appendChild(me.document.createTextNode(utils.html(node.data.replace(/&nbsp;/g, " "))))
                        }
                        if (!node.nextSibling() && frag.lastChild.nodeName == "BR") {
                            frag.removeChild(frag.lastChild)
                        }
                    });
                    rng.insertNode(frag).select()
                }
                return true
            }
        });
        me.addListener("keydown", function(cmd, evt) {
            var me = this,
                keyCode = evt.keyCode || evt.which;
            if (keyCode == 40) {
                var rng = me.selection.getRange(),
                    pre, start = rng.startContainer;
                if (rng.collapsed && (pre = domUtils.findParentByTagName(rng.startContainer, "pre", true)) && !pre.nextSibling) {
                    var last = pre.lastChild;
                    while (last && last.nodeName == "BR") {
                        last = last.previousSibling
                    }
                    if (last === start || rng.startContainer === pre && rng.startOffset == pre.childNodes.length) {
                        me.execCommand("insertparagraph");
                        domUtils.preventDefault(evt)
                    }
                }
            }
        });
        me.addListener("delkeydown", function(type, evt) {
            var rng = this.selection.getRange();
            rng.txtToElmBoundary(true);
            var start = rng.startContainer;
            if (domUtils.isTagNode(start, "pre") && rng.collapsed && domUtils.isStartInblock(rng)) {
                var p = me.document.createElement("p");
                domUtils.fillNode(me.document, p);
                start.parentNode.insertBefore(p, start);
                domUtils.remove(start);
                rng.setStart(p, 0).setCursor(false, true);
                domUtils.preventDefault(evt);
                return true
            }
        })
    };
    UE.commands["cleardoc"] = {
        execCommand: function(cmdName) {
            var me = this,
                enterTag = me.options.enterTag,
                range = me.selection.getRange();
            if (enterTag == "br") {
                me.body.innerHTML = "<br/>";
                range.setStart(me.body, 0).setCursor()
            } else {
                me.body.innerHTML = "<p>" + (ie ? "" : "<br/>") + "</p>";
                range.setStart(me.body.firstChild, 0).setCursor(false, true)
            }
            setTimeout(function() {
                me.fireEvent("clearDoc")
            }, 0)
        }
    };
    UE.plugin.register("anchor", function() {
        return {
            bindEvents: {
                "ready": function() {
                    utils.cssRule("anchor", ".anchorclass{background: url('" + this.options.themePath + this.options.theme + "/images/anchor.gif') no-repeat scroll left center transparent;cursor: auto;display: inline-block;height: 16px;width: 15px;}", this.document)
                }
            },
            outputRule: function(root) {
                utils.each(root.getNodesByTagName("img"), function(a) {
                    var val;
                    if (val = a.getAttr("anchorname")) {
                        a.tagName = "a";
                        a.setAttr({
                            anchorname: "",
                            name: val,
                            "class": ""
                        })
                    }
                })
            },
            inputRule: function(root) {
                utils.each(root.getNodesByTagName("a"), function(a) {
                    var val;
                    if ((val = a.getAttr("name")) && !a.getAttr("href")) {
                        a.tagName = "img";
                        a.setAttr({
                            anchorname: a.getAttr("name"),
                            "class": "anchorclass"
                        });
                        a.setAttr("name")
                    }
                })
            },
            commands: {
                "anchor": {
                    execCommand: function(cmd, name) {
                        var range = this.selection.getRange(),
                            img = range.getClosedNode();
                        if (img && img.getAttribute("anchorname")) {
                            if (name) {
                                img.setAttribute("anchorname", name)
                            } else {
                                range.setStartBefore(img).setCursor();
                                domUtils.remove(img)
                            }
                        } else {
                            if (name) {
                                var anchor = this.document.createElement("img");
                                range.collapse(true);
                                domUtils.setAttributes(anchor, {
                                    "anchorname": name,
                                    "class": "anchorclass"
                                });
                                range.insertNode(anchor).setStartAfter(anchor).setCursor(false, true)
                            }
                        }
                    }
                }
            }
        }
    });
    UE.plugins["wordcount"] = function() {
        var me = this;
        me.setOpt("wordCount", true);
        me.addListener("contentchange", function() {
            me.fireEvent("wordcount")
        });
        var timer;
        me.addListener("ready", function() {
            var me = this;
            domUtils.on(me.body, "keyup", function(evt) {
                var code = evt.keyCode || evt.which,
                    ignores = {
                        "16": 1,
                        "18": 1,
                        "20": 1,
                        "37": 1,
                        "38": 1,
                        "39": 1,
                        "40": 1
                    };
                if (code in ignores) {
                    return
                }
                clearTimeout(timer);
                timer = setTimeout(function() {
                    me.fireEvent("wordcount")
                }, 200)
            })
        })
    };
    UE.plugins["pagebreak"] = function() {
        var me = this,
            notBreakTags = ["td"];
        me.setOpt("pageBreakTag", "_ueditor_page_break_tag_");

        function fillNode(node) {
            if (domUtils.isEmptyBlock(node)) {
                var firstChild = node.firstChild,
                    tmpNode;
                while (firstChild && firstChild.nodeType == 1 && domUtils.isEmptyBlock(firstChild)) {
                    tmpNode = firstChild;
                    firstChild = firstChild.firstChild
                }!tmpNode && (tmpNode = node);
                domUtils.fillNode(me.document, tmpNode)
            }
        }
        me.ready(function() {
            utils.cssRule("pagebreak", ".pagebreak{display:block;clear:both !important;cursor:default !important;width: 100% !important;margin:0;}", me.document)
        });

        function isHr(node) {
            return node && node.nodeType == 1 && node.tagName == "HR" && node.className == "pagebreak"
        }
        me.addInputRule(function(root) {
            root.traversal(function(node) {
                if (node.type == "text" && node.data == me.options.pageBreakTag) {
                    var hr = UE.uNode.createElement('<hr class="pagebreak" noshade="noshade" size="5" style="-webkit-user-select: none;">');
                    node.parentNode.insertBefore(hr, node);
                    node.parentNode.removeChild(node)
                }
            })
        });
        me.addOutputRule(function(node) {
            utils.each(node.getNodesByTagName("hr"), function(n) {
                if (n.getAttr("class") == "pagebreak") {
                    var txt = UE.uNode.createText(me.options.pageBreakTag);
                    n.parentNode.insertBefore(txt, n);
                    n.parentNode.removeChild(n)
                }
            })
        });
        me.commands["pagebreak"] = {
            execCommand: function() {
                var range = me.selection.getRange(),
                    hr = me.document.createElement("hr");
                domUtils.setAttributes(hr, {
                    "class": "pagebreak",
                    noshade: "noshade",
                    size: "5"
                });
                domUtils.unSelectable(hr);
                var node = domUtils.findParentByTagName(range.startContainer, notBreakTags, true),
                    parents = [],
                    pN;
                if (node) {
                    switch (node.tagName) {
                        case "TD":
                            pN = node.parentNode;
                            if (!pN.previousSibling) {
                                var table = domUtils.findParentByTagName(pN, "table");
                                table.parentNode.insertBefore(hr, table);
                                parents = domUtils.findParents(hr, true)
                            } else {
                                pN.parentNode.insertBefore(hr, pN);
                                parents = domUtils.findParents(hr)
                            }
                            pN = parents[1];
                            if (hr !== pN) {
                                domUtils.breakParent(hr, pN)
                            }
                            me.fireEvent("afteradjusttable", me.document)
                    }
                } else {
                    if (!range.collapsed) {
                        range.deleteContents();
                        var start = range.startContainer;
                        while (!domUtils.isBody(start) && domUtils.isBlockElm(start) && domUtils.isEmptyNode(start)) {
                            range.setStartBefore(start).collapse(true);
                            domUtils.remove(start);
                            start = range.startContainer
                        }
                    }
                    range.insertNode(hr);
                    var pN = hr.parentNode,
                        nextNode;
                    while (!domUtils.isBody(pN)) {
                        domUtils.breakParent(hr, pN);
                        nextNode = hr.nextSibling;
                        if (nextNode && domUtils.isEmptyBlock(nextNode)) {
                            domUtils.remove(nextNode)
                        }
                        pN = hr.parentNode
                    }
                    nextNode = hr.nextSibling;
                    var pre = hr.previousSibling;
                    if (isHr(pre)) {
                        domUtils.remove(pre)
                    } else {
                        pre && fillNode(pre)
                    }
                    if (!nextNode) {
                        var p = me.document.createElement("p");
                        hr.parentNode.appendChild(p);
                        domUtils.fillNode(me.document, p);
                        range.setStart(p, 0).collapse(true)
                    } else {
                        if (isHr(nextNode)) {
                            domUtils.remove(nextNode)
                        } else {
                            fillNode(nextNode)
                        }
                        range.setEndAfter(hr).collapse(false)
                    }
                    range.select(true)
                }
            }
        }
    };
    UE.plugin.register("wordimage", function() {
        var me = this,
            images = [];
        return {
            commands: {
                "wordimage": {
                    execCommand: function() {
                        var images = domUtils.getElementsByTagName(me.body, "img");
                        var urlList = [];
                        for (var i = 0, ci; ci = images[i++];) {
                            var url = ci.getAttribute("word_img");
                            url && urlList.push(url)
                        }
                        return urlList
                    },
                    queryCommandState: function() {
                        images = domUtils.getElementsByTagName(me.body, "img");
                        for (var i = 0, ci; ci = images[i++];) {
                            if (ci.getAttribute("word_img")) {
                                return 1
                            }
                        }
                        return -1
                    },
                    notNeedUndo: true
                }
            },
            inputRule: function(root) {
                utils.each(root.getNodesByTagName("img"), function(img) {
                    var attrs = img.attrs,
                        flag = parseInt(attrs.width) < 128 || parseInt(attrs.height) < 43,
                        opt = me.options,
                        src = opt.UEDITOR_HOME_URL + "themes/default/images/spacer.gif";
                    if (attrs["src"] && /^(?:(file:\/+))/.test(attrs["src"])) {
                        img.setAttr({
                            width: attrs.width,
                            height: attrs.height,
                            alt: attrs.alt,
                            word_img: attrs.src,
                            src: src,
                            "style": "background:url(" + (flag ? opt.themePath + opt.theme + "/images/word.gif" : opt.langPath + opt.lang + "/images/localimage.png") + ") no-repeat center center;border:1px solid #ddd"
                        })
                    }
                })
            }
        }
    });
    UE.plugins["dragdrop"] = function() {
        var me = this;
        me.ready(function() {
            domUtils.on(this.body, "dragend", function() {
                var rng = me.selection.getRange();
                var node = rng.getClosedNode() || me.selection.getStart();
                if (node && node.tagName == "IMG") {
                    var pre = node.previousSibling,
                        next;
                    while (next = node.nextSibling) {
                        if (next.nodeType == 1 && next.tagName == "SPAN" && !next.firstChild) {
                            domUtils.remove(next)
                        } else {
                            break
                        }
                    }
                    if ((pre && pre.nodeType == 1 && !domUtils.isEmptyBlock(pre) || !pre) && (!next || next && !domUtils.isEmptyBlock(next))) {
                        if (pre && pre.tagName == "P" && !domUtils.isEmptyBlock(pre)) {
                            pre.appendChild(node);
                            domUtils.moveChild(next, pre);
                            domUtils.remove(next)
                        } else {
                            if (next && next.tagName == "P" && !domUtils.isEmptyBlock(next)) {
                                next.insertBefore(node, next.firstChild)
                            }
                        }
                        if (pre && pre.tagName == "P" && domUtils.isEmptyBlock(pre)) {
                            domUtils.remove(pre)
                        }
                        if (next && next.tagName == "P" && domUtils.isEmptyBlock(next)) {
                            domUtils.remove(next)
                        }
                        rng.selectNode(node).select();
                        me.fireEvent("saveScene")
                    }
                }
            })
        });
        me.addListener("keyup", function(type, evt) {
            var keyCode = evt.keyCode || evt.which;
            if (keyCode == 13) {
                var rng = me.selection.getRange(),
                    node;
                if (node = domUtils.findParentByTagName(rng.startContainer, "p", true)) {
                    if (domUtils.getComputedStyle(node, "text-align") == "center") {
                        domUtils.removeStyle(node, "text-align")
                    }
                }
            }
        })
    };
    UE.plugins["undo"] = function() {
        var saveSceneTimer;
        var me = this,
            maxUndoCount = me.options.maxUndoCount || 20,
            maxInputCount = me.options.maxInputCount || 20,
            fillchar = new RegExp(domUtils.fillChar + "|</hr>", "gi");
        var noNeedFillCharTags = {
            ol: 1,
            ul: 1,
            table: 1,
            tbody: 1,
            tr: 1,
            body: 1
        };
        var orgState = me.options.autoClearEmptyNode;

        function compareAddr(indexA, indexB) {
            if (indexA.length != indexB.length) {
                return 0
            }
            for (var i = 0, l = indexA.length; i < l; i++) {
                if (indexA[i] != indexB[i]) {
                    return 0
                }
            }
            return 1
        }
        function compareRangeAddress(rngAddrA, rngAddrB) {
            if (rngAddrA.collapsed != rngAddrB.collapsed) {
                return 0
            }
            if (!compareAddr(rngAddrA.startAddress, rngAddrB.startAddress) || !compareAddr(rngAddrA.endAddress, rngAddrB.endAddress)) {
                return 0
            }
            return 1
        }
        function UndoManager() {
            this.list = [];
            this.index = 0;
            this.hasUndo = false;
            this.hasRedo = false;
            this.undo = function() {
                if (this.hasUndo) {
                    if (!this.list[this.index - 1] && this.list.length == 1) {
                        this.reset();
                        return
                    }
                    while (this.list[this.index].content == this.list[this.index - 1].content) {
                        this.index--;
                        if (this.index == 0) {
                            return this.restore(0)
                        }
                    }
                    this.restore(--this.index)
                }
            };
            this.redo = function() {
                if (this.hasRedo) {
                    while (this.list[this.index].content == this.list[this.index + 1].content) {
                        this.index++;
                        if (this.index == this.list.length - 1) {
                            return this.restore(this.index)
                        }
                    }
                    this.restore(++this.index)
                }
            };
            this.restore = function() {
                var me = this.editor;
                var scene = this.list[this.index];
                var root = UE.htmlparser(scene.content.replace(fillchar, ""));
                me.options.autoClearEmptyNode = false;
                me.filterInputRule(root);
                me.options.autoClearEmptyNode = orgState;
                me.document.body.innerHTML = root.toHtml();
                me.fireEvent("afterscencerestore");
                if (browser.ie) {
                    utils.each(domUtils.getElementsByTagName(me.document, "td th caption p"), function(node) {
                        if (domUtils.isEmptyNode(node)) {
                            domUtils.fillNode(me.document, node)
                        }
                    })
                }
                try {
                    var rng = new dom.Range(me.document).moveToAddress(scene.address);
                    rng.select(noNeedFillCharTags[rng.startContainer.nodeName.toLowerCase()])
                } catch (e) {}
                this.update();
                this.clearKey();
                me.fireEvent("reset", true)
            };
            this.getScene = function() {
                var me = this.editor;
                var rng = me.selection.getRange(),
                    rngAddress = rng.createAddress(false, true);
                me.fireEvent("beforegetscene");
                var root = UE.htmlparser(me.body.innerHTML);
                me.options.autoClearEmptyNode = false;
                me.filterOutputRule(root);
                me.options.autoClearEmptyNode = orgState;
                var cont = root.toHtml();
                me.fireEvent("aftergetscene");
                return {
                    address: rngAddress,
                    content: cont
                }
            };
            this.save = function(notCompareRange, notSetCursor) {
                clearTimeout(saveSceneTimer);
                var currentScene = this.getScene(notSetCursor),
                    lastScene = this.list[this.index];
                if (lastScene && lastScene.content != currentScene.content) {
                    me.trigger("contentchange")
                }
                if (lastScene && lastScene.content == currentScene.content && (notCompareRange ? 1 : compareRangeAddress(lastScene.address, currentScene.address))) {
                    return
                }
                this.list = this.list.slice(0, this.index + 1);
                this.list.push(currentScene);
                if (this.list.length > maxUndoCount) {
                    this.list.shift()
                }
                this.index = this.list.length - 1;
                this.clearKey();
                this.update()
            };
            this.update = function() {
                this.hasRedo = !! this.list[this.index + 1];
                this.hasUndo = !! this.list[this.index - 1]
            };
            this.reset = function() {
                this.list = [];
                this.index = 0;
                this.hasUndo = false;
                this.hasRedo = false;
                this.clearKey()
            };
            this.clearKey = function() {
                keycont = 0;
                lastKeyCode = null
            }
        }
        me.undoManger = new UndoManager();
        me.undoManger.editor = me;

        function saveScene() {
            this.undoManger.save()
        }
        me.addListener("saveScene", function() {
            var args = Array.prototype.splice.call(arguments, 1);
            this.undoManger.save.apply(this.undoManger, args)
        });
        me.addListener("reset", function(type, exclude) {
            if (!exclude) {
                this.undoManger.reset()
            }
        });
        me.commands["redo"] = me.commands["undo"] = {
            execCommand: function(cmdName) {
                this.undoManger[cmdName]()
            },
            queryCommandState: function(cmdName) {
                return this.undoManger["has" + (cmdName.toLowerCase() == "undo" ? "Undo" : "Redo")] ? 0 : -1
            },
            notNeedUndo: 1
        };
        var keys = {
                16: 1,
                17: 1,
                18: 1,
                37: 1,
                38: 1,
                39: 1,
                40: 1
            },
            keycont = 0,
            lastKeyCode;
        var inputType = false;
        me.addListener("ready", function() {
            domUtils.on(this.body, "compositionstart", function() {
                inputType = true
            });
            domUtils.on(this.body, "compositionend", function() {
                inputType = false
            })
        });
        me.addshortcutkey({
            "Undo": "ctrl+90",
            "Redo": "ctrl+89"
        });
        var isCollapsed = true;
        me.addListener("keydown", function(type, evt) {
            var me = this;
            var keyCode = evt.keyCode || evt.which;
            if (!keys[keyCode] && !evt.ctrlKey && !evt.metaKey && !evt.shiftKey && !evt.altKey) {
                if (inputType) {
                    return
                }
                if (!me.selection.getRange().collapsed) {
                    me.undoManger.save(false, true);
                    isCollapsed = false;
                    return
                }
                if (me.undoManger.list.length == 0) {
                    me.undoManger.save(true)
                }
                clearTimeout(saveSceneTimer);

                function save(cont) {
                    cont.undoManger.save(false, true);
                    cont.fireEvent("selectionchange")
                }
                saveSceneTimer = setTimeout(function() {
                    if (inputType) {
                        var interalTimer = setInterval(function() {
                            if (!inputType) {
                                save(me);
                                clearInterval(interalTimer)
                            }
                        }, 300);
                        return
                    }
                    save(me)
                }, 200);
                lastKeyCode = keyCode;
                keycont++;
                if (keycont >= maxInputCount) {
                    save(me)
                }
            }
        });
        me.addListener("keyup", function(type, evt) {
            var keyCode = evt.keyCode || evt.which;
            if (!keys[keyCode] && !evt.ctrlKey && !evt.metaKey && !evt.shiftKey && !evt.altKey) {
                if (inputType) {
                    return
                }
                if (!isCollapsed) {
                    this.undoManger.save(false, true);
                    isCollapsed = true
                }
            }
        });
        me.stopCmdUndo = function() {
            me.__hasEnterExecCommand = true
        };
        me.startCmdUndo = function() {
            me.__hasEnterExecCommand = false
        }
    };
    UE.plugin.register("copy", function() {
        var me = this;

        function initZeroClipboard() {
            ZeroClipboard.config({
                debug: false,
                swfPath: me.options.UEDITOR_HOME_URL + "third-party/zeroclipboard/ZeroClipboard.swf"
            });
            var client = me.zeroclipboard = new ZeroClipboard();
            client.on("copy", function(e) {
                var client = e.client,
                    rng = me.selection.getRange(),
                    div = document.createElement("div");
                div.appendChild(rng.cloneContents());
                client.setText(div.innerText || div.textContent);
                client.setHtml(div.innerHTML);
                rng.select()
            });
            client.on("mouseover mouseout", function(e) {
                var target = e.target;
                if (e.type == "mouseover") {
                    domUtils.addClass(target, "edui-state-hover")
                } else {
                    if (e.type == "mouseout") {
                        domUtils.removeClasses(target, "edui-state-hover")
                    }
                }
            });
            client.on("wrongflash noflash", function() {
                ZeroClipboard.destroy()
            })
        }
        return {
            bindEvents: {
                "ready": function() {
                    if (!browser.ie) {
                        if (window.ZeroClipboard) {
                            initZeroClipboard()
                        } else {
                            utils.loadFile(document, {
                                src: me.options.UEDITOR_HOME_URL + "third-party/zeroclipboard/ZeroClipboard.js",
                                tag: "script",
                                type: "text/javascript",
                                defer: "defer"
                            }, function() {
                                initZeroClipboard()
                            })
                        }
                    }
                }
            },
            commands: {
                "copy": {
                    execCommand: function(cmd) {
                        if (!me.document.execCommand("copy")) {
                            alert(me.getLang("copymsg"))
                        }
                    }
                }
            }
        }
    });
    UE.plugins["paste"] = function() {
        function getClipboardData(callback) {
            var doc = this.document;
            if (doc.getElementById("baidu_pastebin")) {
                return
            }
            var range = this.selection.getRange(),
                bk = range.createBookmark(),
                pastebin = doc.createElement("div");
            pastebin.id = "baidu_pastebin";
            browser.webkit && pastebin.appendChild(doc.createTextNode(domUtils.fillChar + domUtils.fillChar));
            doc.body.appendChild(pastebin);
            bk.start.style.display = "";
            pastebin.style.cssText = "position:absolute;width:1px;height:1px;overflow:hidden;left:-1000px;white-space:nowrap;top:" + domUtils.getXY(bk.start).y + "px";
            range.selectNodeContents(pastebin).select(true);
            setTimeout(function() {
                if (browser.webkit) {
                    for (var i = 0, pastebins = doc.querySelectorAll("#baidu_pastebin"), pi; pi = pastebins[i++];) {
                        if (domUtils.isEmptyNode(pi)) {
                            domUtils.remove(pi)
                        } else {
                            pastebin = pi;
                            break
                        }
                    }
                }
                try {
                    pastebin.parentNode.removeChild(pastebin)
                } catch (e) {}
                range.moveToBookmark(bk).select(true);
                callback(pastebin)
            }, 0)
        }
        var me = this;
        me.setOpt({
            retainOnlyLabelPasted: false
        });
        var txtContent, htmlContent, address;

        function getPureHtml(html) {
            return html.replace(/<(\/?)([\w\-]+)([^>]*)>/gi, function(a, b, tagName, attrs) {
                tagName = tagName.toLowerCase();
                if ({
                        img: 1
                    }[tagName]) {
                    return a
                }
                attrs = attrs.replace(/([\w\-]*?)\s*=\s*(("([^"]*)")|('([^']*)')|([^\s>]+))/gi, function(str, atr, val) {
                    if ({
                            "src": 1,
                            "href": 1,
                            "name": 1
                        }[atr.toLowerCase()]) {
                        return atr + "=" + val + " "
                    }
                    return ""
                });
                if ({
                        "span": 1,
                        "div": 1
                    }[tagName]) {
                    return ""
                } else {
                    return "<" + b + tagName + " " + utils.trim(attrs) + ">"
                }
            })
        }
        function filter(div) {
            var html;
            if (div.firstChild) {
                var nodes = domUtils.getElementsByTagName(div, "span");
                for (var i = 0, ni; ni = nodes[i++];) {
                    if (ni.id == "_baidu_cut_start" || ni.id == "_baidu_cut_end") {
                        domUtils.remove(ni)
                    }
                }
                if (browser.webkit) {
                    var brs = div.querySelectorAll("div br");
                    for (var i = 0, bi; bi = brs[i++];) {
                        var pN = bi.parentNode;
                        if (pN.tagName == "DIV" && pN.childNodes.length == 1) {
                            pN.innerHTML = "<p><br/></p>";
                            domUtils.remove(pN)
                        }
                    }
                    var divs = div.querySelectorAll("#baidu_pastebin");
                    for (var i = 0, di; di = divs[i++];) {
                        var tmpP = me.document.createElement("p");
                        di.parentNode.insertBefore(tmpP, di);
                        while (di.firstChild) {
                            tmpP.appendChild(di.firstChild)
                        }
                        domUtils.remove(di)
                    }
                    var metas = div.querySelectorAll("meta");
                    for (var i = 0, ci; ci = metas[i++];) {
                        domUtils.remove(ci)
                    }
                    var brs = div.querySelectorAll("br");
                    for (i = 0; ci = brs[i++];) {
                        if (/^apple-/i.test(ci.className)) {
                            domUtils.remove(ci)
                        }
                    }
                }
                if (browser.gecko) {
                    var dirtyNodes = div.querySelectorAll("[_moz_dirty]");
                    for (i = 0; ci = dirtyNodes[i++];) {
                        ci.removeAttribute("_moz_dirty")
                    }
                }
                if (!browser.ie) {
                    var spans = div.querySelectorAll("span.Apple-style-span");
                    for (var i = 0, ci; ci = spans[i++];) {
                        domUtils.remove(ci, true)
                    }
                }
                html = div.innerHTML;
                html = UE.filterWord(html);
                var root = UE.htmlparser(html);
                if (me.options.filterRules) {
                    UE.filterNode(root, me.options.filterRules)
                }
                me.filterInputRule(root);
                if (browser.webkit) {
                    var br = root.lastChild();
                    if (br && br.type == "element" && br.tagName == "br") {
                        root.removeChild(br)
                    }
                    utils.each(me.body.querySelectorAll("div"), function(node) {
                        if (domUtils.isEmptyBlock(node)) {
                            domUtils.remove(node, true)
                        }
                    })
                }
                html = {
                    "html": root.toHtml()
                };
                me.fireEvent("beforepaste", html, root);
                if (!html.html) {
                    return
                }
                root = UE.htmlparser(html.html, true);
                if (me.queryCommandState("pasteplain") === 1) {
                    me.execCommand("insertHtml", UE.filterNode(root, me.options.filterTxtRules).toHtml(), true)
                } else {
                    UE.filterNode(root, me.options.filterTxtRules);
                    txtContent = root.toHtml();
                    htmlContent = html.html;
                    address = me.selection.getRange().createAddress(true);
                    me.execCommand("insertHtml", me.getOpt("retainOnlyLabelPasted") === true ? getPureHtml(htmlContent) : htmlContent, true)
                }
                me.fireEvent("afterpaste", html)
            }
        }
        me.addListener("pasteTransfer", function(cmd, plainType) {
            if (address && txtContent && htmlContent && txtContent != htmlContent) {
                var range = me.selection.getRange();
                range.moveToAddress(address, true);
                if (!range.collapsed) {
                    while (!domUtils.isBody(range.startContainer)) {
                        var start = range.startContainer;
                        if (start.nodeType == 1) {
                            start = start.childNodes[range.startOffset];
                            if (!start) {
                                range.setStartBefore(range.startContainer);
                                continue
                            }
                            var pre = start.previousSibling;
                            if (pre && pre.nodeType == 3 && new RegExp("^[\n\r\t " + domUtils.fillChar + "]*$").test(pre.nodeValue)) {
                                range.setStartBefore(pre)
                            }
                        }
                        if (range.startOffset == 0) {
                            range.setStartBefore(range.startContainer)
                        } else {
                            break
                        }
                    }
                    while (!domUtils.isBody(range.endContainer)) {
                        var end = range.endContainer;
                        if (end.nodeType == 1) {
                            end = end.childNodes[range.endOffset];
                            if (!end) {
                                range.setEndAfter(range.endContainer);
                                continue
                            }
                            var next = end.nextSibling;
                            if (next && next.nodeType == 3 && new RegExp("^[\n\r\t" + domUtils.fillChar + "]*$").test(next.nodeValue)) {
                                range.setEndAfter(next)
                            }
                        }
                        if (range.endOffset == range.endContainer[range.endContainer.nodeType == 3 ? "nodeValue" : "childNodes"].length) {
                            range.setEndAfter(range.endContainer)
                        } else {
                            break
                        }
                    }
                }
                range.deleteContents();
                range.select(true);
                me.__hasEnterExecCommand = true;
                var html = htmlContent;
                if (plainType === 2) {
                    html = getPureHtml(html)
                } else {
                    if (plainType) {
                        html = txtContent
                    }
                }
                me.execCommand("inserthtml", html, true);
                me.__hasEnterExecCommand = false;
                var rng = me.selection.getRange();
                while (!domUtils.isBody(rng.startContainer) && !rng.startOffset && rng.startContainer[rng.startContainer.nodeType == 3 ? "nodeValue" : "childNodes"].length) {
                    rng.setStartBefore(rng.startContainer)
                }
                var tmpAddress = rng.createAddress(true);
                address.endAddress = tmpAddress.startAddress
            }
        });
        me.addListener("ready", function() {
            domUtils.on(me.body, "cut", function() {
                var range = me.selection.getRange();
                if (!range.collapsed && me.undoManger) {
                    me.undoManger.save()
                }
            });
            domUtils.on(me.body, browser.ie || browser.opera ? "keydown" : "paste", function(e) {
                if ((browser.ie || browser.opera) && ((!e.ctrlKey && !e.metaKey) || e.keyCode != "86")) {
                    return
                }
                getClipboardData.call(me, function(div) {
                    filter(div)
                })
            })
        });
        me.commands["paste"] = {
            execCommand: function(cmd) {
                if (browser.ie) {
                    getClipboardData.call(me, function(div) {
                        filter(div)
                    });
                    me.document.execCommand("paste")
                } else {
                    alert(me.getLang("pastemsg"))
                }
            }
        }
    };
    UE.plugins["pasteplain"] = function() {
        var me = this;
        me.setOpt({
            "pasteplain": false,
            "filterTxtRules": function() {
                function transP(node) {
                    node.tagName = "p";
                    node.setStyle()
                }
                function removeNode(node) {
                    node.parentNode.removeChild(node, true)
                }
                return {
                    "-": "script style object iframe embed input select",
                    "p": {
                        $: {}
                    },
                    "br": {
                        $: {}
                    },
                    div: function(node) {
                        var tmpNode, p = UE.uNode.createElement("p");
                        while (tmpNode = node.firstChild()) {
                            if (tmpNode.type == "text" || !UE.dom.dtd.$block[tmpNode.tagName]) {
                                p.appendChild(tmpNode)
                            } else {
                                if (p.firstChild()) {
                                    node.parentNode.insertBefore(p, node);
                                    p = UE.uNode.createElement("p")
                                } else {
                                    node.parentNode.insertBefore(tmpNode, node)
                                }
                            }
                        }
                        if (p.firstChild()) {
                            node.parentNode.insertBefore(p, node)
                        }
                        node.parentNode.removeChild(node)
                    },
                    ol: removeNode,
                    ul: removeNode,
                    dl: removeNode,
                    dt: removeNode,
                    dd: removeNode,
                    "li": removeNode,
                    "caption": transP,
                    "th": transP,
                    "tr": transP,
                    "h1": transP,
                    "h2": transP,
                    "h3": transP,
                    "h4": transP,
                    "h5": transP,
                    "h6": transP,
                    "td": function(node) {
                        var txt = !! node.innerText();
                        if (txt) {
                            node.parentNode.insertAfter(UE.uNode.createText(" &nbsp; &nbsp;"), node)
                        }
                        node.parentNode.removeChild(node, node.innerText())
                    }
                }
            }()
        });
        var pasteplain = me.options.pasteplain;
        me.commands["pasteplain"] = {
            queryCommandState: function() {
                return pasteplain ? 1 : 0
            },
            execCommand: function() {
                pasteplain = !pasteplain | 0
            },
            notNeedUndo: 1
        }
    };
    UE.plugins["list"] = function() {
        var me = this,
            notExchange = {
                "TD": 1,
                "PRE": 1,
                "BLOCKQUOTE": 1
            };
        var customStyle = {
            "cn": "cn-1-",
            "cn1": "cn-2-",
            "cn2": "cn-3-",
            "num": "num-1-",
            "num1": "num-2-",
            "num2": "num-3-",
            "dash": "dash",
            "dot": "dot"
        };
        me.setOpt({
            "autoTransWordToList": false,
            "insertorderedlist": {
                "num": "",
                "num1": "",
                "num2": "",
                "cn": "",
                "cn1": "",
                "cn2": "",
                "decimal": "",
                "lower-alpha": "",
                "lower-roman": "",
                "upper-alpha": "",
                "upper-roman": ""
            },
            "insertunorderedlist": {
                "circle": "",
                "disc": "",
                "square": "",
                "dash": "",
                "dot": ""
            },
            listDefaultPaddingLeft: "30",
            listiconpath: "http://bs.baidu.com/listicon/",
            maxListLevel: -1,
            disablePInList: false
        });

        function listToArray(list) {
            var arr = [];
            for (var p in list) {
                arr.push(p)
            }
            return arr
        }
        var listStyle = {
            "OL": listToArray(me.options.insertorderedlist),
            "UL": listToArray(me.options.insertunorderedlist)
        };
        var liiconpath = me.options.listiconpath;
        for (var s in customStyle) {
            if (!me.options.insertorderedlist.hasOwnProperty(s) && !me.options.insertunorderedlist.hasOwnProperty(s)) {
                delete customStyle[s]
            }
        }
        me.ready(function() {
            var customCss = [];
            for (var p in customStyle) {
                if (p == "dash" || p == "dot") {
                    customCss.push("li.list-" + customStyle[p] + "{background-image:url(" + liiconpath + customStyle[p] + ".gif)}");
                    customCss.push("ul.custom_" + p + "{list-style:none;}ul.custom_" + p + " li{background-position:0 3px;background-repeat:no-repeat}")
                } else {
                    for (var i = 0; i < 99; i++) {
                        customCss.push("li.list-" + customStyle[p] + i + "{background-image:url(" + liiconpath + "list-" + customStyle[p] + i + ".gif)}")
                    }
                    customCss.push("ol.custom_" + p + "{list-style:none;}ol.custom_" + p + " li{background-position:0 3px;background-repeat:no-repeat}")
                }
                switch (p) {
                    case "cn":
                        customCss.push("li.list-" + p + "-paddingleft-1{padding-left:25px}");
                        customCss.push("li.list-" + p + "-paddingleft-2{padding-left:40px}");
                        customCss.push("li.list-" + p + "-paddingleft-3{padding-left:55px}");
                        break;
                    case "cn1":
                        customCss.push("li.list-" + p + "-paddingleft-1{padding-left:30px}");
                        customCss.push("li.list-" + p + "-paddingleft-2{padding-left:40px}");
                        customCss.push("li.list-" + p + "-paddingleft-3{padding-left:55px}");
                        break;
                    case "cn2":
                        customCss.push("li.list-" + p + "-paddingleft-1{padding-left:40px}");
                        customCss.push("li.list-" + p + "-paddingleft-2{padding-left:55px}");
                        customCss.push("li.list-" + p + "-paddingleft-3{padding-left:68px}");
                        break;
                    case "num":
                    case "num1":
                        customCss.push("li.list-" + p + "-paddingleft-1{padding-left:25px}");
                        break;
                    case "num2":
                        customCss.push("li.list-" + p + "-paddingleft-1{padding-left:35px}");
                        customCss.push("li.list-" + p + "-paddingleft-2{padding-left:40px}");
                        break;
                    case "dash":
                        customCss.push("li.list-" + p + "-paddingleft{padding-left:35px}");
                        break;
                    case "dot":
                        customCss.push("li.list-" + p + "-paddingleft{padding-left:20px}")
                }
            }
            customCss.push(".list-paddingleft-1{padding-left:0}");
            customCss.push(".list-paddingleft-2{padding-left:" + me.options.listDefaultPaddingLeft + "px}");
            customCss.push(".list-paddingleft-3{padding-left:" + me.options.listDefaultPaddingLeft * 2 + "px}");
            utils.cssRule("list", "ol,ul{margin:0;pading:0;" + (browser.ie ? "" : "width:95%") + "}li{clear:both;}" + customCss.join("\n"), me.document)
        });
        me.ready(function() {
            domUtils.on(me.body, "cut", function() {
                setTimeout(function() {
                    var rng = me.selection.getRange(),
                        li;
                    if (!rng.collapsed) {
                        if (li = domUtils.findParentByTagName(rng.startContainer, "li", true)) {
                            if (!li.nextSibling && domUtils.isEmptyBlock(li)) {
                                var pn = li.parentNode,
                                    node;
                                if (node = pn.previousSibling) {
                                    domUtils.remove(pn);
                                    rng.setStartAtLast(node).collapse(true);
                                    rng.select(true)
                                } else {
                                    if (node = pn.nextSibling) {
                                        domUtils.remove(pn);
                                        rng.setStartAtFirst(node).collapse(true);
                                        rng.select(true)
                                    } else {
                                        var tmpNode = me.document.createElement("p");
                                        domUtils.fillNode(me.document, tmpNode);
                                        pn.parentNode.insertBefore(tmpNode, pn);
                                        domUtils.remove(pn);
                                        rng.setStart(tmpNode, 0).collapse(true);
                                        rng.select(true)
                                    }
                                }
                            }
                        }
                    }
                })
            })
        });

        function getStyle(node) {
            var cls = node.className;
            if (domUtils.hasClass(node, /custom_/)) {
                return cls.match(/custom_(\w+)/)[1]
            }
            return domUtils.getStyle(node, "list-style-type")
        }
        me.addListener("beforepaste", function(type, html) {
            var me = this,
                rng = me.selection.getRange(),
                li;
            var root = UE.htmlparser(html.html, true);
            if (li = domUtils.findParentByTagName(rng.startContainer, "li", true)) {
                var list = li.parentNode,
                    tagName = list.tagName == "OL" ? "ul" : "ol";
                utils.each(root.getNodesByTagName(tagName), function(n) {
                    n.tagName = list.tagName;
                    n.setAttr();
                    if (n.parentNode === root) {
                        type = getStyle(list) || (list.tagName == "OL" ? "decimal" : "disc")
                    } else {
                        var className = n.parentNode.getAttr("class");
                        if (className && /custom_/.test(className)) {
                            type = className.match(/custom_(\w+)/)[1]
                        } else {
                            type = n.parentNode.getStyle("list-style-type")
                        }
                        if (!type) {
                            type = list.tagName == "OL" ? "decimal" : "disc"
                        }
                    }
                    var index = utils.indexOf(listStyle[list.tagName], type);
                    if (n.parentNode !== root) {
                        index = index + 1 == listStyle[list.tagName].length ? 0 : index + 1
                    }
                    var currentStyle = listStyle[list.tagName][index];
                    if (customStyle[currentStyle]) {
                        n.setAttr("class", "custom_" + currentStyle)
                    } else {
                        n.setStyle("list-style-type", currentStyle)
                    }
                })
            }
            html.html = root.toHtml()
        });
        me.getOpt("disablePInList") === true && me.addOutputRule(function(root) {
            utils.each(root.getNodesByTagName("li"), function(li) {
                var newChildrens = [],
                    index = 0;
                utils.each(li.children, function(n) {
                    if (n.tagName == "p") {
                        var tmpNode;
                        while (tmpNode = n.children.pop()) {
                            newChildrens.splice(index, 0, tmpNode);
                            tmpNode.parentNode = li;
                            lastNode = tmpNode
                        }
                        tmpNode = newChildrens[newChildrens.length - 1];
                        if (!tmpNode || tmpNode.type != "element" || tmpNode.tagName != "br") {
                            var br = UE.uNode.createElement("br");
                            br.parentNode = li;
                            newChildrens.push(br)
                        }
                        index = newChildrens.length
                    }
                });
                if (newChildrens.length) {
                    li.children = newChildrens
                }
            })
        });
        me.addInputRule(function(root) {
            utils.each(root.getNodesByTagName("li"), function(li) {
                var tmpP = UE.uNode.createElement("p");
                for (var i = 0, ci; ci = li.children[i];) {
                    if (ci.type == "text" || dtd.p[ci.tagName]) {
                        tmpP.appendChild(ci)
                    } else {
                        if (tmpP.firstChild()) {
                            li.insertBefore(tmpP, ci);
                            tmpP = UE.uNode.createElement("p");
                            i = i + 2
                        } else {
                            i++
                        }
                    }
                }
                if (tmpP.firstChild() && !tmpP.parentNode || !li.firstChild()) {
                    li.appendChild(tmpP)
                }
                if (!tmpP.firstChild()) {
                    tmpP.innerHTML(browser.ie ? "&nbsp;" : "<br/>")
                }
                var p = li.firstChild();
                var lastChild = p.lastChild();
                if (lastChild && lastChild.type == "text" && /^\s*$/.test(lastChild.data)) {
                    p.removeChild(lastChild)
                }
            });
            if (me.options.autoTransWordToList) {
                var orderlisttype = {
                        "num1": /^\d+\)/,
                        "decimal": /^\d+\./,
                        "lower-alpha": /^[a-z]+\)/,
                        "upper-alpha": /^[A-Z]+\./,
                        "cn": /^[一二三四六五七八九]+[、]/,
                        "cn2": /^\([一二三四六五七八九]+\)/
                    },
                    unorderlisttype = {
                        "square": "n"
                    };

                function checkListType(content, container) {
                    var span = container.firstChild();
                    if (span && span.type == "element" && span.tagName == "span" && /Wingdings|Symbol/.test(span.getStyle("font-family"))) {
                        for (var p in unorderlisttype) {
                            if (unorderlisttype[p] == span.data) {
                                return p
                            }
                        }
                        return "disc"
                    }
                    for (var p in orderlisttype) {
                        if (orderlisttype[p].test(content)) {
                            return p
                        }
                    }
                }
                utils.each(root.getNodesByTagName("p"), function(node) {
                    if (node.getAttr("class") != "MsoListParagraph") {
                        return
                    }
                    node.setStyle("margin", "");
                    node.setStyle("margin-left", "");
                    node.setAttr("class", "");

                    function appendLi(list, p, type) {
                        if (list.tagName == "ol") {
                            if (browser.ie) {
                                var first = p.firstChild();
                                if (first.type == "element" && first.tagName == "span" && orderlisttype[type].test(first.innerText())) {
                                    p.removeChild(first)
                                }
                            } else {
                                p.innerHTML(p.innerHTML().replace(orderlisttype[type], ""))
                            }
                        } else {
                            p.removeChild(p.firstChild())
                        }
                        var li = UE.uNode.createElement("li");
                        li.appendChild(p);
                        list.appendChild(li)
                    }
                    var tmp = node,
                        type, cacheNode = node;
                    if (node.parentNode.tagName != "li" && (type = checkListType(node.innerText(), node))) {
                        var list = UE.uNode.createElement(me.options.insertorderedlist.hasOwnProperty(type) ? "ol" : "ul");
                        if (customStyle[type]) {
                            list.setAttr("class", "custom_" + type)
                        } else {
                            list.setStyle("list-style-type", type)
                        }
                        while (node && node.parentNode.tagName != "li" && checkListType(node.innerText(), node)) {
                            tmp = node.nextSibling();
                            if (!tmp) {
                                node.parentNode.insertBefore(list, node)
                            }
                            appendLi(list, node, type);
                            node = tmp
                        }
                        if (!list.parentNode && node && node.parentNode) {
                            node.parentNode.insertBefore(list, node)
                        }
                    }
                    var span = cacheNode.firstChild();
                    if (span && span.type == "element" && span.tagName == "span" && /^\s*(&nbsp;)+\s*$/.test(span.innerText())) {
                        span.parentNode.removeChild(span)
                    }
                })
            }
        });
        me.addListener("contentchange", function() {
            adjustListStyle(me.document)
        });

        function adjustListStyle(doc, ignore) {
            utils.each(domUtils.getElementsByTagName(doc, "ol ul"), function(node) {
                if (!domUtils.inDoc(node, doc)) {
                    return
                }
                var parent = node.parentNode;
                if (parent.tagName == node.tagName) {
                    var nodeStyleType = getStyle(node) || (node.tagName == "OL" ? "decimal" : "disc"),
                        parentStyleType = getStyle(parent) || (parent.tagName == "OL" ? "decimal" : "disc");
                    if (nodeStyleType == parentStyleType) {
                        var styleIndex = utils.indexOf(listStyle[node.tagName], nodeStyleType);
                        styleIndex = styleIndex + 1 == listStyle[node.tagName].length ? 0 : styleIndex + 1;
                        setListStyle(node, listStyle[node.tagName][styleIndex])
                    }
                }
                var index = 0,
                    type = 2;
                if (domUtils.hasClass(node, /custom_/)) {
                    if (!(/[ou]l/i.test(parent.tagName) && domUtils.hasClass(parent, /custom_/))) {
                        type = 1
                    }
                } else {
                    if (/[ou]l/i.test(parent.tagName) && domUtils.hasClass(parent, /custom_/)) {
                        type = 3
                    }
                }
                var style = domUtils.getStyle(node, "list-style-type");
                style && (node.style.cssText = "list-style-type:" + style);
                node.className = utils.trim(node.className.replace(/list-paddingleft-\w+/, "")) + " list-paddingleft-" + type;
                utils.each(domUtils.getElementsByTagName(node, "li"), function(li) {
                    li.style.cssText && (li.style.cssText = "");
                    if (!li.firstChild) {
                        domUtils.remove(li);
                        return
                    }
                    if (li.parentNode !== node) {
                        return
                    }
                    index++;
                    if (domUtils.hasClass(node, /custom_/)) {
                        var paddingLeft = 1,
                            currentStyle = getStyle(node);
                        if (node.tagName == "OL") {
                            if (currentStyle) {
                                switch (currentStyle) {
                                    case "cn":
                                    case "cn1":
                                    case "cn2":
                                        if (index > 10 && (index % 10 == 0 || index > 10 && index < 20)) {
                                            paddingLeft = 2
                                        } else {
                                            if (index > 20) {
                                                paddingLeft = 3
                                            }
                                        }
                                        break;
                                    case "num2":
                                        if (index > 9) {
                                            paddingLeft = 2
                                        }
                                }
                            }
                            li.className = "list-" + customStyle[currentStyle] + index + " " + "list-" + currentStyle + "-paddingleft-" + paddingLeft
                        } else {
                            li.className = "list-" + customStyle[currentStyle] + " " + "list-" + currentStyle + "-paddingleft"
                        }
                    } else {
                        li.className = li.className.replace(/list-[\w\-]+/gi, "")
                    }
                    var className = li.getAttribute("class");
                    if (className !== null && !className.replace(/\s/g, "")) {
                        domUtils.removeAttributes(li, "class")
                    }
                });
                !ignore && adjustList(node, node.tagName.toLowerCase(), getStyle(node) || domUtils.getStyle(node, "list-style-type"), true)
            })
        }
        function adjustList(list, tag, style, ignoreEmpty) {
            var nextList = list.nextSibling;
            if (nextList && nextList.nodeType == 1 && nextList.tagName.toLowerCase() == tag && (getStyle(nextList) || domUtils.getStyle(nextList, "list-style-type") || (tag == "ol" ? "decimal" : "disc")) == style) {
                domUtils.moveChild(nextList, list);
                if (nextList.childNodes.length == 0) {
                    domUtils.remove(nextList)
                }
            }
            if (nextList && domUtils.isFillChar(nextList)) {
                domUtils.remove(nextList)
            }
            var preList = list.previousSibling;
            if (preList && preList.nodeType == 1 && preList.tagName.toLowerCase() == tag && (getStyle(preList) || domUtils.getStyle(preList, "list-style-type") || (tag == "ol" ? "decimal" : "disc")) == style) {
                domUtils.moveChild(list, preList)
            }
            if (preList && domUtils.isFillChar(preList)) {
                domUtils.remove(preList)
            }!ignoreEmpty && domUtils.isEmptyBlock(list) && domUtils.remove(list);
            if (getStyle(list)) {
                adjustListStyle(list.ownerDocument, true)
            }
        }
        function setListStyle(list, style) {
            if (customStyle[style]) {
                list.className = "custom_" + style
            }
            try {
                domUtils.setStyle(list, "list-style-type", style)
            } catch (e) {}
        }
        function clearEmptySibling(node) {
            var tmpNode = node.previousSibling;
            if (tmpNode && domUtils.isEmptyBlock(tmpNode)) {
                domUtils.remove(tmpNode)
            }
            tmpNode = node.nextSibling;
            if (tmpNode && domUtils.isEmptyBlock(tmpNode)) {
                domUtils.remove(tmpNode)
            }
        }
        me.addListener("keydown", function(type, evt) {
            function preventAndSave() {
                evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false);
                me.fireEvent("contentchange");
                me.undoManger && me.undoManger.save()
            }
            function findList(node, filterFn) {
                while (node && !domUtils.isBody(node)) {
                    if (filterFn(node)) {
                        return null
                    }
                    if (node.nodeType == 1 && /[ou]l/i.test(node.tagName)) {
                        return node
                    }
                    node = node.parentNode
                }
                return null
            }
            var keyCode = evt.keyCode || evt.which;
            if (keyCode == 13 && !evt.shiftKey) {
                var rng = me.selection.getRange(),
                    parent = domUtils.findParent(rng.startContainer, function(node) {
                        return domUtils.isBlockElm(node)
                    }, true),
                    li = domUtils.findParentByTagName(rng.startContainer, "li", true);
                if (parent && parent.tagName != "PRE" && !li) {
                    var html = parent.innerHTML.replace(new RegExp(domUtils.fillChar, "g"), "");
                    if (/^\s*1\s*\.[^\d]/.test(html)) {
                        parent.innerHTML = html.replace(/^\s*1\s*\./, "");
                        rng.setStartAtLast(parent).collapse(true).select();
                        me.__hasEnterExecCommand = true;
                        me.execCommand("insertorderedlist");
                        me.__hasEnterExecCommand = false
                    }
                }
                var range = me.selection.getRange(),
                    start = findList(range.startContainer, function(node) {
                        return node.tagName == "TABLE"
                    }),
                    end = range.collapsed ? start : findList(range.endContainer, function(node) {
                        return node.tagName == "TABLE"
                    });
                if (start && end && start === end) {
                    if (!range.collapsed) {
                        start = domUtils.findParentByTagName(range.startContainer, "li", true);
                        end = domUtils.findParentByTagName(range.endContainer, "li", true);
                        if (start && end && start === end) {
                            range.deleteContents();
                            li = domUtils.findParentByTagName(range.startContainer, "li", true);
                            if (li && domUtils.isEmptyBlock(li)) {
                                pre = li.previousSibling;
                                next = li.nextSibling;
                                p = me.document.createElement("p");
                                domUtils.fillNode(me.document, p);
                                parentList = li.parentNode;
                                if (pre && next) {
                                    range.setStart(next, 0).collapse(true).select(true);
                                    domUtils.remove(li)
                                } else {
                                    if (!pre && !next || !pre) {
                                        parentList.parentNode.insertBefore(p, parentList)
                                    } else {
                                        li.parentNode.parentNode.insertBefore(p, parentList.nextSibling)
                                    }
                                    domUtils.remove(li);
                                    if (!parentList.firstChild) {
                                        domUtils.remove(parentList)
                                    }
                                    range.setStart(p, 0).setCursor()
                                }
                                preventAndSave();
                                return
                            }
                        } else {
                            var tmpRange = range.cloneRange(),
                                bk = tmpRange.collapse(false).createBookmark();
                            range.deleteContents();
                            tmpRange.moveToBookmark(bk);
                            var li = domUtils.findParentByTagName(tmpRange.startContainer, "li", true);
                            clearEmptySibling(li);
                            tmpRange.select();
                            preventAndSave();
                            return
                        }
                    }
                    li = domUtils.findParentByTagName(range.startContainer, "li", true);
                    if (li) {
                        if (domUtils.isEmptyBlock(li)) {
                            bk = range.createBookmark();
                            var parentList = li.parentNode;
                            if (li !== parentList.lastChild) {
                                domUtils.breakParent(li, parentList);
                                clearEmptySibling(li)
                            } else {
                                parentList.parentNode.insertBefore(li, parentList.nextSibling);
                                if (domUtils.isEmptyNode(parentList)) {
                                    domUtils.remove(parentList)
                                }
                            }
                            if (!dtd.$list[li.parentNode.tagName]) {
                                if (!domUtils.isBlockElm(li.firstChild)) {
                                    p = me.document.createElement("p");
                                    li.parentNode.insertBefore(p, li);
                                    while (li.firstChild) {
                                        p.appendChild(li.firstChild)
                                    }
                                    domUtils.remove(li)
                                } else {
                                    domUtils.remove(li, true)
                                }
                            }
                            range.moveToBookmark(bk).select()
                        } else {
                            var first = li.firstChild;
                            if (!first || !domUtils.isBlockElm(first)) {
                                var p = me.document.createElement("p");
                                !li.firstChild && domUtils.fillNode(me.document, p);
                                while (li.firstChild) {
                                    p.appendChild(li.firstChild)
                                }
                                li.appendChild(p);
                                first = p
                            }
                            var span = me.document.createElement("span");
                            range.insertNode(span);
                            domUtils.breakParent(span, li);
                            var nextLi = span.nextSibling;
                            first = nextLi.firstChild;
                            if (!first) {
                                p = me.document.createElement("p");
                                domUtils.fillNode(me.document, p);
                                nextLi.appendChild(p);
                                first = p
                            }
                            if (domUtils.isEmptyNode(first)) {
                                first.innerHTML = "";
                                domUtils.fillNode(me.document, first)
                            }
                            range.setStart(first, 0).collapse(true).shrinkBoundary().select();
                            domUtils.remove(span);
                            var pre = nextLi.previousSibling;
                            if (pre && domUtils.isEmptyBlock(pre)) {
                                pre.innerHTML = "<p></p>";
                                domUtils.fillNode(me.document, pre.firstChild)
                            }
                        }
                        preventAndSave()
                    }
                }
            }
            if (keyCode == 8) {
                range = me.selection.getRange();
                if (range.collapsed && domUtils.isStartInblock(range)) {
                    tmpRange = range.cloneRange().trimBoundary();
                    li = domUtils.findParentByTagName(range.startContainer, "li", true);
                    if (li && domUtils.isStartInblock(tmpRange)) {
                        start = domUtils.findParentByTagName(range.startContainer, "p", true);
                        if (start && start !== li.firstChild) {
                            var parentList = domUtils.findParentByTagName(start, ["ol", "ul"]);
                            domUtils.breakParent(start, parentList);
                            clearEmptySibling(start);
                            me.fireEvent("contentchange");
                            range.setStart(start, 0).setCursor(false, true);
                            me.fireEvent("saveScene");
                            domUtils.preventDefault(evt);
                            return
                        }
                        if (li && (pre = li.previousSibling)) {
                            if (keyCode == 46 && li.childNodes.length) {
                                return
                            }
                            if (dtd.$list[pre.tagName]) {
                                pre = pre.lastChild
                            }
                            me.undoManger && me.undoManger.save();
                            first = li.firstChild;
                            if (domUtils.isBlockElm(first)) {
                                if (domUtils.isEmptyNode(first)) {
                                    pre.appendChild(first);
                                    range.setStart(first, 0).setCursor(false, true);
                                    while (li.firstChild) {
                                        pre.appendChild(li.firstChild)
                                    }
                                } else {
                                    span = me.document.createElement("span");
                                    range.insertNode(span);
                                    if (domUtils.isEmptyBlock(pre)) {
                                        pre.innerHTML = ""
                                    }
                                    domUtils.moveChild(li, pre);
                                    range.setStartBefore(span).collapse(true).select(true);
                                    domUtils.remove(span)
                                }
                            } else {
                                if (domUtils.isEmptyNode(li)) {
                                    var p = me.document.createElement("p");
                                    pre.appendChild(p);
                                    range.setStart(p, 0).setCursor()
                                } else {
                                    range.setEnd(pre, pre.childNodes.length).collapse().select(true);
                                    while (li.firstChild) {
                                        pre.appendChild(li.firstChild)
                                    }
                                }
                            }
                            domUtils.remove(li);
                            me.fireEvent("contentchange");
                            me.fireEvent("saveScene");
                            domUtils.preventDefault(evt);
                            return
                        }
                        if (li && !li.previousSibling) {
                            var parentList = li.parentNode;
                            var bk = range.createBookmark();
                            if (domUtils.isTagNode(parentList.parentNode, "ol ul")) {
                                parentList.parentNode.insertBefore(li, parentList);
                                if (domUtils.isEmptyNode(parentList)) {
                                    domUtils.remove(parentList)
                                }
                            } else {
                                while (li.firstChild) {
                                    parentList.parentNode.insertBefore(li.firstChild, parentList)
                                }
                                domUtils.remove(li);
                                if (domUtils.isEmptyNode(parentList)) {
                                    domUtils.remove(parentList)
                                }
                            }
                            range.moveToBookmark(bk).setCursor(false, true);
                            me.fireEvent("contentchange");
                            me.fireEvent("saveScene");
                            domUtils.preventDefault(evt);
                            return
                        }
                    }
                }
            }
        });
        me.addListener("keyup", function(type, evt) {
            var keyCode = evt.keyCode || evt.which;
            if (keyCode == 8) {
                var rng = me.selection.getRange(),
                    list;
                if (list = domUtils.findParentByTagName(rng.startContainer, ["ol", "ul"], true)) {
                    adjustList(list, list.tagName.toLowerCase(), getStyle(list) || domUtils.getComputedStyle(list, "list-style-type"), true)
                }
            }
        });
        me.addListener("tabkeydown", function() {
            var range = me.selection.getRange();

            function checkLevel(li) {
                if (me.options.maxListLevel != -1) {
                    var level = li.parentNode,
                        levelNum = 0;
                    while (/[ou]l/i.test(level.tagName)) {
                        levelNum++;
                        level = level.parentNode
                    }
                    if (levelNum >= me.options.maxListLevel) {
                        return true
                    }
                }
            }
            var li = domUtils.findParentByTagName(range.startContainer, "li", true);
            if (li) {
                var bk;
                if (range.collapsed) {
                    if (checkLevel(li)) {
                        return true
                    }
                    var parentLi = li.parentNode,
                        list = me.document.createElement(parentLi.tagName),
                        index = utils.indexOf(listStyle[list.tagName], getStyle(parentLi) || domUtils.getComputedStyle(parentLi, "list-style-type"));
                    index = index + 1 == listStyle[list.tagName].length ? 0 : index + 1;
                    var currentStyle = listStyle[list.tagName][index];
                    setListStyle(list, currentStyle);
                    if (domUtils.isStartInblock(range)) {
                        me.fireEvent("saveScene");
                        bk = range.createBookmark();
                        parentLi.insertBefore(list, li);
                        list.appendChild(li);
                        adjustList(list, list.tagName.toLowerCase(), currentStyle);
                        me.fireEvent("contentchange");
                        range.moveToBookmark(bk).select(true);
                        return true
                    }
                } else {
                    me.fireEvent("saveScene");
                    bk = range.createBookmark();
                    for (var i = 0, closeList, parents = domUtils.findParents(li), ci; ci = parents[i++];) {
                        if (domUtils.isTagNode(ci, "ol ul")) {
                            closeList = ci;
                            break
                        }
                    }
                    var current = li;
                    if (bk.end) {
                        while (current && !(domUtils.getPosition(current, bk.end) & domUtils.POSITION_FOLLOWING)) {
                            if (checkLevel(current)) {
                                current = domUtils.getNextDomNode(current, false, null, function(node) {
                                    return node !== closeList
                                });
                                continue
                            }
                            var parentLi = current.parentNode,
                                list = me.document.createElement(parentLi.tagName),
                                index = utils.indexOf(listStyle[list.tagName], getStyle(parentLi) || domUtils.getComputedStyle(parentLi, "list-style-type"));
                            var currentIndex = index + 1 == listStyle[list.tagName].length ? 0 : index + 1;
                            var currentStyle = listStyle[list.tagName][currentIndex];
                            setListStyle(list, currentStyle);
                            parentLi.insertBefore(list, current);
                            while (current && !(domUtils.getPosition(current, bk.end) & domUtils.POSITION_FOLLOWING)) {
                                li = current.nextSibling;
                                list.appendChild(current);
                                if (!li || domUtils.isTagNode(li, "ol ul")) {
                                    if (li) {
                                        while (li = li.firstChild) {
                                            if (li.tagName == "LI") {
                                                break
                                            }
                                        }
                                    } else {
                                        li = domUtils.getNextDomNode(current, false, null, function(node) {
                                            return node !== closeList
                                        })
                                    }
                                    break
                                }
                                current = li
                            }
                            adjustList(list, list.tagName.toLowerCase(), currentStyle);
                            current = li
                        }
                    }
                    me.fireEvent("contentchange");
                    range.moveToBookmark(bk).select();
                    return true
                }
            }
        });

        function getLi(start) {
            while (start && !domUtils.isBody(start)) {
                if (start.nodeName == "TABLE") {
                    return null
                }
                if (start.nodeName == "LI") {
                    return start
                }
                start = start.parentNode
            }
        }
        me.commands["insertorderedlist"] = me.commands["insertunorderedlist"] = {
            execCommand: function(command, style) {
                if (!style) {
                    style = command.toLowerCase() == "insertorderedlist" ? "decimal" : "disc"
                }
                var me = this,
                    range = this.selection.getRange(),
                    filterFn = function(node) {
                        return node.nodeType == 1 ? node.tagName.toLowerCase() != "br" : !domUtils.isWhitespace(node)
                    },
                    tag = command.toLowerCase() == "insertorderedlist" ? "ol" : "ul",
                    frag = me.document.createDocumentFragment();
                range.adjustmentBoundary().shrinkBoundary();
                var bko = range.createBookmark(true),
                    start = getLi(me.document.getElementById(bko.start)),
                    modifyStart = 0,
                    end = getLi(me.document.getElementById(bko.end)),
                    modifyEnd = 0,
                    startParent, endParent, list, tmp;
                if (start || end) {
                    start && (startParent = start.parentNode);
                    if (!bko.end) {
                        end = start
                    }
                    end && (endParent = end.parentNode);
                    if (startParent === endParent) {
                        while (start !== end) {
                            tmp = start;
                            start = start.nextSibling;
                            if (!domUtils.isBlockElm(tmp.firstChild)) {
                                var p = me.document.createElement("p");
                                while (tmp.firstChild) {
                                    p.appendChild(tmp.firstChild)
                                }
                                tmp.appendChild(p)
                            }
                            frag.appendChild(tmp)
                        }
                        tmp = me.document.createElement("span");
                        startParent.insertBefore(tmp, end);
                        if (!domUtils.isBlockElm(end.firstChild)) {
                            p = me.document.createElement("p");
                            while (end.firstChild) {
                                p.appendChild(end.firstChild)
                            }
                            end.appendChild(p)
                        }
                        frag.appendChild(end);
                        domUtils.breakParent(tmp, startParent);
                        if (domUtils.isEmptyNode(tmp.previousSibling)) {
                            domUtils.remove(tmp.previousSibling)
                        }
                        if (domUtils.isEmptyNode(tmp.nextSibling)) {
                            domUtils.remove(tmp.nextSibling)
                        }
                        var nodeStyle = getStyle(startParent) || domUtils.getComputedStyle(startParent, "list-style-type") || (command.toLowerCase() == "insertorderedlist" ? "decimal" : "disc");
                        if (startParent.tagName.toLowerCase() == tag && nodeStyle == style) {
                            for (var i = 0, ci, tmpFrag = me.document.createDocumentFragment(); ci = frag.firstChild;) {
                                if (domUtils.isTagNode(ci, "ol ul")) {
                                    tmpFrag.appendChild(ci)
                                } else {
                                    while (ci.firstChild) {
                                        tmpFrag.appendChild(ci.firstChild);
                                        domUtils.remove(ci)
                                    }
                                }
                            }
                            tmp.parentNode.insertBefore(tmpFrag, tmp)
                        } else {
                            list = me.document.createElement(tag);
                            setListStyle(list, style);
                            list.appendChild(frag);
                            tmp.parentNode.insertBefore(list, tmp)
                        }
                        domUtils.remove(tmp);
                        list && adjustList(list, tag, style);
                        range.moveToBookmark(bko).select();
                        return
                    }
                    if (start) {
                        while (start) {
                            tmp = start.nextSibling;
                            if (domUtils.isTagNode(start, "ol ul")) {
                                frag.appendChild(start)
                            } else {
                                var tmpfrag = me.document.createDocumentFragment(),
                                    hasBlock = 0;
                                while (start.firstChild) {
                                    if (domUtils.isBlockElm(start.firstChild)) {
                                        hasBlock = 1
                                    }
                                    tmpfrag.appendChild(start.firstChild)
                                }
                                if (!hasBlock) {
                                    var tmpP = me.document.createElement("p");
                                    tmpP.appendChild(tmpfrag);
                                    frag.appendChild(tmpP)
                                } else {
                                    frag.appendChild(tmpfrag)
                                }
                                domUtils.remove(start)
                            }
                            start = tmp
                        }
                        startParent.parentNode.insertBefore(frag, startParent.nextSibling);
                        if (domUtils.isEmptyNode(startParent)) {
                            range.setStartBefore(startParent);
                            domUtils.remove(startParent)
                        } else {
                            range.setStartAfter(startParent)
                        }
                        modifyStart = 1
                    }
                    if (end && domUtils.inDoc(endParent, me.document)) {
                        start = endParent.firstChild;
                        while (start && start !== end) {
                            tmp = start.nextSibling;
                            if (domUtils.isTagNode(start, "ol ul")) {
                                frag.appendChild(start)
                            } else {
                                tmpfrag = me.document.createDocumentFragment();
                                hasBlock = 0;
                                while (start.firstChild) {
                                    if (domUtils.isBlockElm(start.firstChild)) {
                                        hasBlock = 1
                                    }
                                    tmpfrag.appendChild(start.firstChild)
                                }
                                if (!hasBlock) {
                                    tmpP = me.document.createElement("p");
                                    tmpP.appendChild(tmpfrag);
                                    frag.appendChild(tmpP)
                                } else {
                                    frag.appendChild(tmpfrag)
                                }
                                domUtils.remove(start)
                            }
                            start = tmp
                        }
                        var tmpDiv = domUtils.createElement(me.document, "div", {
                            "tmpDiv": 1
                        });
                        domUtils.moveChild(end, tmpDiv);
                        frag.appendChild(tmpDiv);
                        domUtils.remove(end);
                        endParent.parentNode.insertBefore(frag, endParent);
                        range.setEndBefore(endParent);
                        if (domUtils.isEmptyNode(endParent)) {
                            domUtils.remove(endParent)
                        }
                        modifyEnd = 1
                    }
                }
                if (!modifyStart) {
                    range.setStartBefore(me.document.getElementById(bko.start))
                }
                if (bko.end && !modifyEnd) {
                    range.setEndAfter(me.document.getElementById(bko.end))
                }
                range.enlarge(true, function(node) {
                    return notExchange[node.tagName]
                });
                frag = me.document.createDocumentFragment();
                var bk = range.createBookmark(),
                    current = domUtils.getNextDomNode(bk.start, false, filterFn),
                    tmpRange = range.cloneRange(),
                    tmpNode, block = domUtils.isBlockElm;
                while (current && current !== bk.end && (domUtils.getPosition(current, bk.end) & domUtils.POSITION_PRECEDING)) {
                    if (current.nodeType == 3 || dtd.li[current.tagName]) {
                        if (current.nodeType == 1 && dtd.$list[current.tagName]) {
                            while (current.firstChild) {
                                frag.appendChild(current.firstChild)
                            }
                            tmpNode = domUtils.getNextDomNode(current, false, filterFn);
                            domUtils.remove(current);
                            current = tmpNode;
                            continue
                        }
                        tmpNode = current;
                        tmpRange.setStartBefore(current);
                        while (current && current !== bk.end && (!block(current) || domUtils.isBookmarkNode(current))) {
                            tmpNode = current;
                            current = domUtils.getNextDomNode(current, false, null, function(node) {
                                return !notExchange[node.tagName]
                            })
                        }
                        if (current && block(current)) {
                            tmp = domUtils.getNextDomNode(tmpNode, false, filterFn);
                            if (tmp && domUtils.isBookmarkNode(tmp)) {
                                current = domUtils.getNextDomNode(tmp, false, filterFn);
                                tmpNode = tmp
                            }
                        }
                        tmpRange.setEndAfter(tmpNode);
                        current = domUtils.getNextDomNode(tmpNode, false, filterFn);
                        var li = range.document.createElement("li");
                        li.appendChild(tmpRange.extractContents());
                        if (domUtils.isEmptyNode(li)) {
                            var tmpNode = range.document.createElement("p");
                            while (li.firstChild) {
                                tmpNode.appendChild(li.firstChild)
                            }
                            li.appendChild(tmpNode)
                        }
                        frag.appendChild(li)
                    } else {
                        current = domUtils.getNextDomNode(current, true, filterFn)
                    }
                }
                range.moveToBookmark(bk).collapse(true);
                list = me.document.createElement(tag);
                setListStyle(list, style);
                list.appendChild(frag);
                range.insertNode(list);
                adjustList(list, tag, style);
                for (var i = 0, ci, tmpDivs = domUtils.getElementsByTagName(list, "div"); ci = tmpDivs[i++];) {
                    if (ci.getAttribute("tmpDiv")) {
                        domUtils.remove(ci, true)
                    }
                }
                range.moveToBookmark(bko).select()
            },
            queryCommandState: function(command) {
                var tag = command.toLowerCase() == "insertorderedlist" ? "ol" : "ul";
                var path = this.selection.getStartElementPath();
                for (var i = 0, ci; ci = path[i++];) {
                    if (ci.nodeName == "TABLE") {
                        return 0
                    }
                    if (tag == ci.nodeName.toLowerCase()) {
                        return 1
                    }
                }
                return 0
            },
            queryCommandValue: function(command) {
                var tag = command.toLowerCase() == "insertorderedlist" ? "ol" : "ul";
                var path = this.selection.getStartElementPath(),
                    node;
                for (var i = 0, ci; ci = path[i++];) {
                    if (ci.nodeName == "TABLE") {
                        node = null;
                        break
                    }
                    if (tag == ci.nodeName.toLowerCase()) {
                        node = ci;
                        break
                    }
                }
                return node ? getStyle(node) || domUtils.getComputedStyle(node, "list-style-type") : null
            }
        }
    };
    (function() {
        var sourceEditors = {
            textarea: function(editor, holder) {
                var textarea = holder.ownerDocument.createElement("textarea");
                textarea.style.cssText = "position:absolute;resize:none;width:100%;height:100%;border:0;padding:0;margin:0;overflow-y:auto;";
                if (browser.ie && browser.version < 8) {
                    textarea.style.width = holder.offsetWidth + "px";
                    textarea.style.height = holder.offsetHeight + "px";
                    holder.onresize = function() {
                        textarea.style.width = holder.offsetWidth + "px";
                        textarea.style.height = holder.offsetHeight + "px"
                    }
                }
                holder.appendChild(textarea);
                return {
                    setContent: function(content) {
                        textarea.value = content
                    },
                    getContent: function() {
                        return textarea.value
                    },
                    select: function() {
                        var range;
                        if (browser.ie) {
                            range = textarea.createTextRange();
                            range.collapse(true);
                            range.select()
                        } else {
                            textarea.setSelectionRange(0, 0);
                            textarea.focus()
                        }
                    },
                    dispose: function() {
                        holder.removeChild(textarea);
                        holder.onresize = null;
                        textarea = null;
                        holder = null
                    }
                }
            },
            codemirror: function(editor, holder) {
                var codeEditor = window.CodeMirror(holder, {
                    mode: "text/html",
                    tabMode: "indent",
                    lineNumbers: true,
                    lineWrapping: true
                });
                var dom = codeEditor.getWrapperElement();
                dom.style.cssText = 'position:absolute;left:0;top:0;width:100%;height:100%;font-family:consolas,"Courier new",monospace;font-size:13px;';
                codeEditor.getScrollerElement().style.cssText = "position:absolute;left:0;top:0;width:100%;height:100%;";
                codeEditor.refresh();
                return {
                    getCodeMirror: function() {
                        return codeEditor
                    },
                    setContent: function(content) {
                        codeEditor.setValue(content)
                    },
                    getContent: function() {
                        return codeEditor.getValue()
                    },
                    select: function() {
                        codeEditor.focus()
                    },
                    dispose: function() {
                        holder.removeChild(dom);
                        dom = null;
                        codeEditor = null
                    }
                }
            }
        };
        UE.plugins["source"] = function() {
            var me = this;
            var opt = this.options;
            var sourceMode = false;
            var sourceEditor;
            var orgSetContent;
            opt.sourceEditor = browser.ie ? "textarea" : (opt.sourceEditor || "codemirror");
            me.setOpt({
                sourceEditorFirst: false
            });

            function createSourceEditor(holder) {
                return sourceEditors[opt.sourceEditor == "codemirror" && window.CodeMirror ? "codemirror" : "textarea"](me, holder)
            }
            var bakCssText;
            var oldGetContent, bakAddress;
            me.commands["source"] = {
                execCommand: function() {
                    sourceMode = !sourceMode;
                    if (sourceMode) {
                        bakAddress = me.selection.getRange().createAddress(false, true);
                        me.undoManger && me.undoManger.save(true);
                        if (browser.gecko) {
                            me.body.contentEditable = false
                        }
                        bakCssText = me.iframe.style.cssText;
                        me.iframe.style.cssText += "position:absolute;left:-32768px;top:-32768px;";
                        me.fireEvent("beforegetcontent");
                        var root = UE.htmlparser(me.body.innerHTML);
                        me.filterOutputRule(root);
                        root.traversal(function(node) {
                            if (node.type == "element") {
                                switch (node.tagName) {
                                    case "td":
                                    case "th":
                                    case "caption":
                                        if (node.children && node.children.length == 1) {
                                            if (node.firstChild().tagName == "br") {
                                                node.removeChild(node.firstChild())
                                            }
                                        }
                                        break;
                                    case "pre":
                                        node.innerText(node.innerText().replace(/&nbsp;/g, " "))
                                }
                            }
                        });
                        me.fireEvent("aftergetcontent");
                        var content = root.toHtml(true);
                        sourceEditor = createSourceEditor(me.iframe.parentNode);
                        sourceEditor.setContent(content);
                        orgSetContent = me.setContent;
                        me.setContent = function(html) {
                            var root = UE.htmlparser(html);
                            me.filterInputRule(root);
                            html = root.toHtml();
                            sourceEditor.setContent(html)
                        };
                        setTimeout(function() {
                            sourceEditor.select();
                            me.addListener("fullscreenchanged", function() {
                                try {
                                    sourceEditor.getCodeMirror().refresh()
                                } catch (e) {}
                            })
                        });
                        oldGetContent = me.getContent;
                        me.getContent = function() {
                            return sourceEditor.getContent() || "<p>" + (browser.ie ? "" : "<br/>") + "</p>"
                        }
                    } else {
                        me.iframe.style.cssText = bakCssText;
                        var cont = sourceEditor.getContent() || "<p>" + (browser.ie ? "" : "<br/>") + "</p>";
                        cont = cont.replace(new RegExp("[\\r\\t\\n ]*</?(\\w+)\\s*(?:[^>]*)>", "g"), function(a, b) {
                            if (b && !dtd.$inlineWithA[b.toLowerCase()]) {
                                return a.replace(/(^[\n\r\t ]*)|([\n\r\t ]*$)/g, "")
                            }
                            return a.replace(/(^[\n\r\t]*)|([\n\r\t]*$)/g, "")
                        });
                        me.setContent = orgSetContent;
                        me.setContent(cont);
                        sourceEditor.dispose();
                        sourceEditor = null;
                        me.getContent = oldGetContent;
                        var first = me.body.firstChild;
                        if (!first) {
                            me.body.innerHTML = "<p>" + (browser.ie ? "" : "<br/>") + "</p>";
                            first = me.body.firstChild
                        }
                        me.undoManger && me.undoManger.save(true);
                        if (browser.gecko) {
                            var input = document.createElement("input");
                            input.style.cssText = "position:absolute;left:0;top:-32768px";
                            document.body.appendChild(input);
                            me.body.contentEditable = false;
                            setTimeout(function() {
                                domUtils.setViewportOffset(input, {
                                    left: -32768,
                                    top: 0
                                });
                                input.focus();
                                setTimeout(function() {
                                    me.body.contentEditable = true;
                                    me.selection.getRange().moveToAddress(bakAddress).select(true);
                                    domUtils.remove(input)
                                })
                            })
                        } else {
                            try {
                                me.selection.getRange().moveToAddress(bakAddress).select(true)
                            } catch (e) {}
                        }
                    }
                    this.fireEvent("sourcemodechanged", sourceMode)
                },
                queryCommandState: function() {
                    return sourceMode | 0
                },
                notNeedUndo: 1
            };
            var oldQueryCommandState = me.queryCommandState;
            me.queryCommandState = function(cmdName) {
                cmdName = cmdName.toLowerCase();
                if (sourceMode) {
                    return cmdName in {
                        "source": 1,
                        "fullscreen": 1
                    } ? 1 : -1
                }
                return oldQueryCommandState.apply(this, arguments)
            };
            if (opt.sourceEditor == "codemirror") {
                me.addListener("ready", function() {
                    utils.loadFile(document, {
                        src: opt.codeMirrorJsUrl || opt.UEDITOR_HOME_URL + "third-party/codemirror/codemirror.js",
                        tag: "script",
                        type: "text/javascript",
                        defer: "defer"
                    }, function() {
                        if (opt.sourceEditorFirst) {
                            setTimeout(function() {
                                me.execCommand("source")
                            }, 0)
                        }
                    });
                    utils.loadFile(document, {
                        tag: "link",
                        rel: "stylesheet",
                        type: "text/css",
                        href: opt.codeMirrorCssUrl || opt.UEDITOR_HOME_URL + "third-party/codemirror/codemirror.css"
                    })
                })
            }
        }
    })();
    UE.plugins["enterkey"] = function() {
        var hTag, me = this,
            tag = me.options.enterTag;
        me.addListener("keyup", function(type, evt) {
            var keyCode = evt.keyCode || evt.which;
            if (keyCode == 13) {
                var range = me.selection.getRange(),
                    start = range.startContainer,
                    doSave;
                if (!browser.ie) {
                    if (/h\d/i.test(hTag)) {
                        if (browser.gecko) {
                            var h = domUtils.findParentByTagName(start, ["h1", "h2", "h3", "h4", "h5", "h6", "blockquote", "caption", "table"], true);
                            if (!h) {
                                me.document.execCommand("formatBlock", false, "<p>");
                                doSave = 1
                            }
                        } else {
                            if (start.nodeType == 1) {
                                var tmp = me.document.createTextNode(""),
                                    div;
                                range.insertNode(tmp);
                                div = domUtils.findParentByTagName(tmp, "div", true);
                                if (div) {
                                    var p = me.document.createElement("p");
                                    while (div.firstChild) {
                                        p.appendChild(div.firstChild)
                                    }
                                    div.parentNode.insertBefore(p, div);
                                    domUtils.remove(div);
                                    range.setStartBefore(tmp).setCursor();
                                    doSave = 1
                                }
                                domUtils.remove(tmp)
                            }
                        }
                        if (me.undoManger && doSave) {
                            me.undoManger.save()
                        }
                    }
                    browser.opera && range.select()
                } else {
                    me.fireEvent("saveScene", true, true)
                }
            }
        });
        me.addListener("keydown", function(type, evt) {
            var keyCode = evt.keyCode || evt.which;
            if (keyCode == 13) {
                if (me.fireEvent("beforeenterkeydown")) {
                    domUtils.preventDefault(evt);
                    return
                }
                me.fireEvent("saveScene", true, true);
                hTag = "";
                var range = me.selection.getRange();
                if (!range.collapsed) {
                    var start = range.startContainer,
                        end = range.endContainer,
                        startTd = domUtils.findParentByTagName(start, "td", true),
                        endTd = domUtils.findParentByTagName(end, "td", true);
                    if (startTd && endTd && startTd !== endTd || !startTd && endTd || startTd && !endTd) {
                        evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false);
                        return
                    }
                }
                if (tag == "p") {
                    if (!browser.ie) {
                        start = domUtils.findParentByTagName(range.startContainer, ["ol", "ul", "p", "h1", "h2", "h3", "h4", "h5", "h6", "blockquote", "caption"], true);
                        if (!start && !browser.opera) {
                            me.document.execCommand("formatBlock", false, "<p>");
                            if (browser.gecko) {
                                range = me.selection.getRange();
                                start = domUtils.findParentByTagName(range.startContainer, "p", true);
                                start && domUtils.removeDirtyAttr(start)
                            }
                        } else {
                            hTag = start.tagName;
                            start.tagName.toLowerCase() == "p" && browser.gecko && domUtils.removeDirtyAttr(start)
                        }
                    }
                } else {
                    evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false);
                    if (!range.collapsed) {
                        range.deleteContents();
                        start = range.startContainer;
                        if (start.nodeType == 1 && (start = start.childNodes[range.startOffset])) {
                            while (start.nodeType == 1) {
                                if (dtd.$empty[start.tagName]) {
                                    range.setStartBefore(start).setCursor();
                                    if (me.undoManger) {
                                        me.undoManger.save()
                                    }
                                    return false
                                }
                                if (!start.firstChild) {
                                    var br = range.document.createElement("br");
                                    start.appendChild(br);
                                    range.setStart(start, 0).setCursor();
                                    if (me.undoManger) {
                                        me.undoManger.save()
                                    }
                                    return false
                                }
                                start = start.firstChild
                            }
                            if (start === range.startContainer.childNodes[range.startOffset]) {
                                br = range.document.createElement("br");
                                range.insertNode(br).setCursor()
                            } else {
                                range.setStart(start, 0).setCursor()
                            }
                        } else {
                            br = range.document.createElement("br");
                            range.insertNode(br).setStartAfter(br).setCursor()
                        }
                    } else {
                        br = range.document.createElement("br");
                        range.insertNode(br);
                        var parent = br.parentNode;
                        if (parent.lastChild === br) {
                            br.parentNode.insertBefore(br.cloneNode(true), br);
                            range.setStartBefore(br)
                        } else {
                            range.setStartAfter(br)
                        }
                        range.setCursor()
                    }
                }
            }
        })
    };
    UE.plugins["keystrokes"] = function() {
        var me = this;
        var collapsed = true;
        me.addListener("keydown", function(type, evt) {
            var keyCode = evt.keyCode || evt.which,
                rng = me.selection.getRange();
            if (!rng.collapsed && !(evt.ctrlKey || evt.shiftKey || evt.altKey || evt.metaKey) && (keyCode >= 65 && keyCode <= 90 || keyCode >= 48 && keyCode <= 57 || keyCode >= 96 && keyCode <= 111 || {
                    13: 1,
                    8: 1,
                    46: 1
                }[keyCode])) {
                var tmpNode = rng.startContainer;
                if (domUtils.isFillChar(tmpNode)) {
                    rng.setStartBefore(tmpNode)
                }
                tmpNode = rng.endContainer;
                if (domUtils.isFillChar(tmpNode)) {
                    rng.setEndAfter(tmpNode)
                }
                rng.txtToElmBoundary();
                if (rng.endContainer && rng.endContainer.nodeType == 1) {
                    tmpNode = rng.endContainer.childNodes[rng.endOffset];
                    if (tmpNode && domUtils.isBr(tmpNode)) {
                        rng.setEndAfter(tmpNode)
                    }
                }
                if (rng.startOffset == 0) {
                    tmpNode = rng.startContainer;
                    if (domUtils.isBoundaryNode(tmpNode, "firstChild")) {
                        tmpNode = rng.endContainer;
                        if (rng.endOffset == (tmpNode.nodeType == 3 ? tmpNode.nodeValue.length : tmpNode.childNodes.length) && domUtils.isBoundaryNode(tmpNode, "lastChild")) {
                            me.fireEvent("saveScene");
                            me.body.innerHTML = "<p>" + (browser.ie ? "" : "<br/>") + "</p>";
                            rng.setStart(me.body.firstChild, 0).setCursor(false, true);
                            me._selectionChange();
                            return
                        }
                    }
                }
            }
            if (keyCode == keymap.Backspace) {
                rng = me.selection.getRange();
                collapsed = rng.collapsed;
                if (me.fireEvent("delkeydown", evt)) {
                    return
                }
                var start, end;
                if (rng.collapsed && rng.inFillChar()) {
                    start = rng.startContainer;
                    if (domUtils.isFillChar(start)) {
                        rng.setStartBefore(start).shrinkBoundary(true).collapse(true);
                        domUtils.remove(start)
                    } else {
                        start.nodeValue = start.nodeValue.replace(new RegExp("^" + domUtils.fillChar), "");
                        rng.startOffset--;
                        rng.collapse(true).select(true)
                    }
                }
                if (start = rng.getClosedNode()) {
                    me.fireEvent("saveScene");
                    rng.setStartBefore(start);
                    domUtils.remove(start);
                    rng.setCursor();
                    me.fireEvent("saveScene");
                    domUtils.preventDefault(evt);
                    return
                }
                if (!browser.ie) {
                    start = domUtils.findParentByTagName(rng.startContainer, "table", true);
                    end = domUtils.findParentByTagName(rng.endContainer, "table", true);
                    if (start && !end || !start && end || start !== end) {
                        evt.preventDefault();
                        return
                    }
                }
            }
            if (keyCode == keymap.Tab) {
                var excludeTagNameForTabKey = {
                    "ol": 1,
                    "ul": 1,
                    "table": 1
                };
                if (me.fireEvent("tabkeydown", evt)) {
                    domUtils.preventDefault(evt);
                    return
                }
                var range = me.selection.getRange();
                me.fireEvent("saveScene");
                for (var i = 0, txt = "", tabSize = me.options.tabSize || 4, tabNode = me.options.tabNode || "&nbsp;"; i < tabSize; i++) {
                    txt += tabNode
                }
                var span = me.document.createElement("span");
                span.innerHTML = txt + domUtils.fillChar;
                if (range.collapsed) {
                    range.insertNode(span.cloneNode(true).firstChild).setCursor(true)
                } else {
                    var filterFn = function(node) {
                        return domUtils.isBlockElm(node) && !excludeTagNameForTabKey[node.tagName.toLowerCase()]
                    };
                    start = domUtils.findParent(range.startContainer, filterFn, true);
                    end = domUtils.findParent(range.endContainer, filterFn, true);
                    if (start && end && start === end) {
                        range.deleteContents();
                        range.insertNode(span.cloneNode(true).firstChild).setCursor(true)
                    } else {
                        var bookmark = range.createBookmark();
                        range.enlarge(true);
                        var bookmark2 = range.createBookmark(),
                            current = domUtils.getNextDomNode(bookmark2.start, false, filterFn);
                        while (current && !(domUtils.getPosition(current, bookmark2.end) & domUtils.POSITION_FOLLOWING)) {
                            current.insertBefore(span.cloneNode(true).firstChild, current.firstChild);
                            current = domUtils.getNextDomNode(current, false, filterFn)
                        }
                        range.moveToBookmark(bookmark2).moveToBookmark(bookmark).select()
                    }
                }
                domUtils.preventDefault(evt)
            }
            if (browser.gecko && keyCode == 46) {
                range = me.selection.getRange();
                if (range.collapsed) {
                    start = range.startContainer;
                    if (domUtils.isEmptyBlock(start)) {
                        var parent = start.parentNode;
                        while (domUtils.getChildCount(parent) == 1 && !domUtils.isBody(parent)) {
                            start = parent;
                            parent = parent.parentNode
                        }
                        if (start === parent.lastChild) {
                            evt.preventDefault()
                        }
                        return
                    }
                }
            }
        });
        me.addListener("keyup", function(type, evt) {
            var keyCode = evt.keyCode || evt.which,
                rng, me = this;
            if (keyCode == keymap.Backspace) {
                if (me.fireEvent("delkeyup")) {
                    return
                }
                rng = me.selection.getRange();
                if (rng.collapsed) {
                    var tmpNode, autoClearTagName = ["h1", "h2", "h3", "h4", "h5", "h6"];
                    if (tmpNode = domUtils.findParentByTagName(rng.startContainer, autoClearTagName, true)) {
                        if (domUtils.isEmptyBlock(tmpNode)) {
                            var pre = tmpNode.previousSibling;
                            if (pre && pre.nodeName != "TABLE") {
                                domUtils.remove(tmpNode);
                                rng.setStartAtLast(pre).setCursor(false, true);
                                return
                            } else {
                                var next = tmpNode.nextSibling;
                                if (next && next.nodeName != "TABLE") {
                                    domUtils.remove(tmpNode);
                                    rng.setStartAtFirst(next).setCursor(false, true);
                                    return
                                }
                            }
                        }
                    }
                    if (domUtils.isBody(rng.startContainer)) {
                        var tmpNode = domUtils.createElement(me.document, "p", {
                            "innerHTML": browser.ie ? domUtils.fillChar : "<br/>"
                        });
                        rng.insertNode(tmpNode).setStart(tmpNode, 0).setCursor(false, true)
                    }
                }
                if (!collapsed && (rng.startContainer.nodeType == 3 || rng.startContainer.nodeType == 1 && domUtils.isEmptyBlock(rng.startContainer))) {
                    if (browser.ie) {
                        var span = rng.document.createElement("span");
                        rng.insertNode(span).setStartBefore(span).collapse(true);
                        rng.select();
                        domUtils.remove(span)
                    } else {
                        rng.select()
                    }
                }
            }
        })
    };
    UE.plugins["fiximgclick"] = (function() {
        var elementUpdated = false;

        function Scale() {
            this.editor = null;
            this.resizer = null;
            this.cover = null;
            this.doc = document;
            this.prePos = {
                x: 0,
                y: 0
            };
            this.startPos = {
                x: 0,
                y: 0
            }
        }(function() {
            var rect = [
                [0, 0, -1, -1],
                [0, 0, 0, -1],
                [0, 0, 1, -1],
                [0, 0, -1, 0],
                [0, 0, 1, 0],
                [0, 0, -1, 1],
                [0, 0, 0, 1],
                [0, 0, 1, 1]
            ];
            Scale.prototype = {
                init: function(editor) {
                    var me = this;
                    me.editor = editor;
                    me.startPos = this.prePos = {
                        x: 0,
                        y: 0
                    };
                    me.dragId = -1;
                    var hands = [],
                        cover = me.cover = document.createElement("div"),
                        resizer = me.resizer = document.createElement("div");
                    cover.id = me.editor.ui.id + "_imagescale_cover";
                    cover.style.cssText = "position:absolute;display:none;z-index:" + (me.editor.options.zIndex) + ";filter:alpha(opacity=0); opacity:0;background:#CCC;";
                    domUtils.on(cover, "mousedown click", function() {
                        me.hide()
                    });
                    for (i = 0; i < 8; i++) {
                        hands.push('<span class="edui-editor-imagescale-hand' + i + '"></span>')
                    }
                    resizer.id = me.editor.ui.id + "_imagescale";
                    resizer.className = "edui-editor-imagescale";
                    resizer.innerHTML = hands.join("");
                    resizer.style.cssText += ";display:none;border:1px solid #3b77ff;z-index:" + (me.editor.options.zIndex) + ";";
                    me.editor.ui.getDom().appendChild(cover);
                    me.editor.ui.getDom().appendChild(resizer);
                    me.initStyle();
                    me.initEvents()
                },
                initStyle: function() {
                    utils.cssRule("imagescale", ".edui-editor-imagescale{display:none;position:absolute;border:1px solid #38B2CE;cursor:hand;-webkit-box-sizing: content-box;-moz-box-sizing: content-box;box-sizing: content-box;}" + ".edui-editor-imagescale span{position:absolute;width:6px;height:6px;overflow:hidden;font-size:0px;display:block;background-color:#3C9DD0;}" + ".edui-editor-imagescale .edui-editor-imagescale-hand0{cursor:nw-resize;top:0;margin-top:-4px;left:0;margin-left:-4px;}" + ".edui-editor-imagescale .edui-editor-imagescale-hand1{cursor:n-resize;top:0;margin-top:-4px;left:50%;margin-left:-4px;}" + ".edui-editor-imagescale .edui-editor-imagescale-hand2{cursor:ne-resize;top:0;margin-top:-4px;left:100%;margin-left:-3px;}" + ".edui-editor-imagescale .edui-editor-imagescale-hand3{cursor:w-resize;top:50%;margin-top:-4px;left:0;margin-left:-4px;}" + ".edui-editor-imagescale .edui-editor-imagescale-hand4{cursor:e-resize;top:50%;margin-top:-4px;left:100%;margin-left:-3px;}" + ".edui-editor-imagescale .edui-editor-imagescale-hand5{cursor:sw-resize;top:100%;margin-top:-3px;left:0;margin-left:-4px;}" + ".edui-editor-imagescale .edui-editor-imagescale-hand6{cursor:s-resize;top:100%;margin-top:-3px;left:50%;margin-left:-4px;}" + ".edui-editor-imagescale .edui-editor-imagescale-hand7{cursor:se-resize;top:100%;margin-top:-3px;left:100%;margin-left:-3px;}")
                },
                initEvents: function() {
                    var me = this;
                    me.startPos.x = me.startPos.y = 0;
                    me.isDraging = false
                },
                _eventHandler: function(e) {
                    var me = this;
                    switch (e.type) {
                        case "mousedown":
                            var hand = e.target || e.srcElement,
                                hand;
                            if (hand.className.indexOf("edui-editor-imagescale-hand") != -1 && me.dragId == -1) {
                                me.dragId = hand.className.slice(-1);
                                me.startPos.x = me.prePos.x = e.clientX;
                                me.startPos.y = me.prePos.y = e.clientY;
                                domUtils.on(me.doc, "mousemove", me.proxy(me._eventHandler, me))
                            }
                            break;
                        case "mousemove":
                            if (me.dragId != -1) {
                                me.updateContainerStyle(me.dragId, {
                                    x: e.clientX - me.prePos.x,
                                    y: e.clientY - me.prePos.y
                                });
                                me.prePos.x = e.clientX;
                                me.prePos.y = e.clientY;
                                elementUpdated = true;
                                me.updateTargetElement()
                            }
                            break;
                        case "mouseup":
                            if (me.dragId != -1) {
                                me.updateContainerStyle(me.dragId, {
                                    x: e.clientX - me.prePos.x,
                                    y: e.clientY - me.prePos.y
                                });
                                me.updateTargetElement();
                                if (me.target.parentNode) {
                                    me.attachTo(me.target)
                                }
                                me.dragId = -1
                            }
                            domUtils.un(me.doc, "mousemove", me.proxy(me._eventHandler, me));
                            if (elementUpdated) {
                                elementUpdated = false;
                                me.editor.fireEvent("contentchange")
                            }
                            break;
                        default:
                            break
                    }
                },
                updateTargetElement: function() {
                    var me = this;
                    domUtils.setStyles(me.target, {
                        "width": me.resizer.style.width,
                        "height": me.resizer.style.height
                    });
                    me.target.width = parseInt(me.resizer.style.width);
                    me.target.height = parseInt(me.resizer.style.height);
                    me.attachTo(me.target)
                },
                updateContainerStyle: function(dir, offset) {
                    var me = this,
                        dom = me.resizer,
                        tmp;
                    if (rect[dir][0] != 0) {
                        tmp = parseInt(dom.style.left) + offset.x;
                        dom.style.left = me._validScaledProp("left", tmp) + "px"
                    }
                    if (rect[dir][1] != 0) {
                        tmp = parseInt(dom.style.top) + offset.y;
                        dom.style.top = me._validScaledProp("top", tmp) + "px"
                    }
                    if (rect[dir][2] != 0) {
                        tmp = dom.clientWidth + rect[dir][2] * offset.x;
                        dom.style.width = me._validScaledProp("width", tmp) + "px"
                    }
                    if (rect[dir][3] != 0) {
                        tmp = dom.clientHeight + rect[dir][3] * offset.y;
                        dom.style.height = me._validScaledProp("height", tmp) + "px"
                    }
                },
                _validScaledProp: function(prop, value) {
                    var ele = this.resizer,
                        wrap = document;
                    value = isNaN(value) ? 0 : value;
                    switch (prop) {
                        case "left":
                            return value < 0 ? 0 : (value + ele.clientWidth) > wrap.clientWidth ? wrap.clientWidth - ele.clientWidth : value;
                        case "top":
                            return value < 0 ? 0 : (value + ele.clientHeight) > wrap.clientHeight ? wrap.clientHeight - ele.clientHeight : value;
                        case "width":
                            return value <= 0 ? 1 : (value + ele.offsetLeft) > wrap.clientWidth ? wrap.clientWidth - ele.offsetLeft : value;
                        case "height":
                            return value <= 0 ? 1 : (value + ele.offsetTop) > wrap.clientHeight ? wrap.clientHeight - ele.offsetTop : value
                    }
                },
                hideCover: function() {
                    this.cover.style.display = "none"
                },
                showCover: function() {
                    var me = this,
                        editorPos = domUtils.getXY(me.editor.ui.getDom()),
                        iframePos = domUtils.getXY(me.editor.iframe);
                    domUtils.setStyles(me.cover, {
                        "width": me.editor.iframe.offsetWidth + "px",
                        "height": me.editor.iframe.offsetHeight + "px",
                        "top": iframePos.y - editorPos.y + "px",
                        "left": iframePos.x - editorPos.x + "px",
                        "position": "absolute",
                        "display": ""
                    })
                },
                show: function(targetObj) {
                    var me = this;
                    me.resizer.style.display = "block";
                    if (targetObj) {
                        me.attachTo(targetObj)
                    }
                    domUtils.on(this.resizer, "mousedown", me.proxy(me._eventHandler, me));
                    domUtils.on(me.doc, "mouseup", me.proxy(me._eventHandler, me));
                    me.showCover();
                    me.editor.fireEvent("afterscaleshow", me);
                    me.editor.fireEvent("saveScene")
                },
                hide: function() {
                    var me = this;
                    me.hideCover();
                    me.resizer.style.display = "none";
                    domUtils.un(me.resizer, "mousedown", me.proxy(me._eventHandler, me));
                    domUtils.un(me.doc, "mouseup", me.proxy(me._eventHandler, me));
                    me.editor.fireEvent("afterscalehide", me)
                },
                proxy: function(fn, context) {
                    return function(e) {
                        return fn.apply(context || this, arguments)
                    }
                },
                attachTo: function(targetObj) {
                    var me = this,
                        target = me.target = targetObj,
                        resizer = this.resizer,
                        imgPos = domUtils.getXY(target),
                        iframePos = domUtils.getXY(me.editor.iframe),
                        editorPos = domUtils.getXY(resizer.parentNode);
                    domUtils.setStyles(resizer, {
                        "width": target.width + "px",
                        "height": target.height + "px",
                        "left": iframePos.x + imgPos.x - me.editor.document.body.scrollLeft - editorPos.x - parseInt(resizer.style.borderLeftWidth) + "px",
                        "top": iframePos.y + imgPos.y - me.editor.document.body.scrollTop - editorPos.y - parseInt(resizer.style.borderTopWidth) + "px"
                    })
                }
            }
        })();
        return function() {
            var me = this,
                imageScale;
            me.setOpt("imageScaleEnabled", true);
            if (!browser.ie && me.options.imageScaleEnabled) {
                me.addListener("click", function(type, e) {
                    var range = me.selection.getRange(),
                        img = range.getClosedNode();
                    if (img && img.tagName == "IMG" && me.body.contentEditable != "false") {
                        if (img.className.indexOf("edui-faked-music") != -1 || img.getAttribute("anchorname") || domUtils.hasClass(img, "loadingclass") || domUtils.hasClass(img, "loaderrorclass")) {
                            return
                        }
                        if (!imageScale) {
                            imageScale = new Scale();
                            imageScale.init(me);
                            me.ui.getDom().appendChild(imageScale.resizer);
                            var _keyDownHandler = function(e) {
                                    imageScale.hide();
                                    if (imageScale.target) {
                                        me.selection.getRange().selectNode(imageScale.target).select()
                                    }
                                },
                                _mouseDownHandler = function(e) {
                                    var ele = e.target || e.srcElement;
                                    if (ele && (ele.className === undefined || ele.className.indexOf("edui-editor-imagescale") == -1)) {
                                        _keyDownHandler(e)
                                    }
                                },
                                timer;
                            me.addListener("afterscaleshow", function(e) {
                                me.addListener("beforekeydown", _keyDownHandler);
                                me.addListener("beforemousedown", _mouseDownHandler);
                                domUtils.on(document, "keydown", _keyDownHandler);
                                domUtils.on(document, "mousedown", _mouseDownHandler);
                                me.selection.getNative().removeAllRanges()
                            });
                            me.addListener("afterscalehide", function(e) {
                                me.removeListener("beforekeydown", _keyDownHandler);
                                me.removeListener("beforemousedown", _mouseDownHandler);
                                domUtils.un(document, "keydown", _keyDownHandler);
                                domUtils.un(document, "mousedown", _mouseDownHandler);
                                var target = imageScale.target;
                                if (target.parentNode) {
                                    me.selection.getRange().selectNode(target).select()
                                }
                            });
                            domUtils.on(imageScale.resizer, "mousedown", function(e) {
                                me.selection.getNative().removeAllRanges();
                                var ele = e.target || e.srcElement;
                                if (ele && ele.className.indexOf("edui-editor-imagescale-hand") == -1) {
                                    timer = setTimeout(function() {
                                        imageScale.hide();
                                        if (imageScale.target) {
                                            me.selection.getRange().selectNode(ele).select()
                                        }
                                    }, 200)
                                }
                            });
                            domUtils.on(imageScale.resizer, "mouseup", function(e) {
                                var ele = e.target || e.srcElement;
                                if (ele && ele.className.indexOf("edui-editor-imagescale-hand") == -1) {
                                    clearTimeout(timer)
                                }
                            })
                        }
                        imageScale.show(img)
                    } else {
                        if (imageScale && imageScale.resizer.style.display != "none") {
                            imageScale.hide()
                        }
                    }
                })
            }
            if (browser.webkit) {
                me.addListener("click", function(type, e) {
                    if (e.target.tagName == "IMG" && me.body.contentEditable != "false") {
                        var range = new dom.Range(me.document);
                        range.selectNode(e.target).select()
                    }
                })
            }
        }
    })();
    UE.plugin.register("autolink", function() {
        var cont = 0;
        return !browser.ie ? {
            bindEvents: {
                "reset": function() {
                    cont = 0
                },
                "keydown": function(type, evt) {
                    var me = this;
                    var keyCode = evt.keyCode || evt.which;
                    if (keyCode == 32 || keyCode == 13) {
                        var sel = me.selection.getNative(),
                            range = sel.getRangeAt(0).cloneRange(),
                            offset, charCode;
                        var start = range.startContainer;
                        while (start.nodeType == 1 && range.startOffset > 0) {
                            start = range.startContainer.childNodes[range.startOffset - 1];
                            if (!start) {
                                break
                            }
                            range.setStart(start, start.nodeType == 1 ? start.childNodes.length : start.nodeValue.length);
                            range.collapse(true);
                            start = range.startContainer
                        }
                        do {
                            if (range.startOffset == 0) {
                                start = range.startContainer.previousSibling;
                                while (start && start.nodeType == 1) {
                                    start = start.lastChild
                                }
                                if (!start || domUtils.isFillChar(start)) {
                                    break
                                }
                                offset = start.nodeValue.length
                            } else {
                                start = range.startContainer;
                                offset = range.startOffset
                            }
                            range.setStart(start, offset - 1);
                            charCode = range.toString().charCodeAt(0)
                        } while (charCode != 160 && charCode != 32);
                        if (range.toString().replace(new RegExp(domUtils.fillChar, "g"), "").match(/(?:https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.)/i)) {
                            while (range.toString().length) {
                                if (/^(?:https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.)/i.test(range.toString())) {
                                    break
                                }
                                try {
                                    range.setStart(range.startContainer, range.startOffset + 1)
                                } catch (e) {
                                    var start = range.startContainer;
                                    while (!(next = start.nextSibling)) {
                                        if (domUtils.isBody(start)) {
                                            return
                                        }
                                        start = start.parentNode
                                    }
                                    range.setStart(next, 0)
                                }
                            }
                            if (domUtils.findParentByTagName(range.startContainer, "a", true)) {
                                return
                            }
                            var a = me.document.createElement("a"),
                                text = me.document.createTextNode(" "),
                                href;
                            me.undoManger && me.undoManger.save();
                            a.appendChild(range.extractContents());
                            a.href = a.innerHTML = a.innerHTML.replace(/<[^>]+>/g, "");
                            href = a.getAttribute("href").replace(new RegExp(domUtils.fillChar, "g"), "");
                            href = /^(?:https?:\/\/)/ig.test(href) ? href : "http://" + href;
                            a.setAttribute("_src", utils.html(href));
                            a.href = utils.html(href);
                            range.insertNode(a);
                            a.parentNode.insertBefore(text, a.nextSibling);
                            range.setStart(text, 0);
                            range.collapse(true);
                            sel.removeAllRanges();
                            sel.addRange(range);
                            me.undoManger && me.undoManger.save()
                        }
                    }
                }
            }
        } : {}
    }, function() {
        var keyCodes = {
            37: 1,
            38: 1,
            39: 1,
            40: 1,
            13: 1,
            32: 1
        };

        function checkIsCludeLink(node) {
            if (node.nodeType == 3) {
                return null
            }
            if (node.nodeName == "A") {
                return node
            }
            var lastChild = node.lastChild;
            while (lastChild) {
                if (lastChild.nodeName == "A") {
                    return lastChild
                }
                if (lastChild.nodeType == 3) {
                    if (domUtils.isWhitespace(lastChild)) {
                        lastChild = lastChild.previousSibling;
                        continue
                    }
                    return null
                }
                lastChild = lastChild.lastChild
            }
        }
        browser.ie && this.addListener("keyup", function(cmd, evt) {
            var me = this,
                keyCode = evt.keyCode;
            if (keyCodes[keyCode]) {
                var rng = me.selection.getRange();
                var start = rng.startContainer;
                if (keyCode == 13) {
                    while (start && !domUtils.isBody(start) && !domUtils.isBlockElm(start)) {
                        start = start.parentNode
                    }
                    if (start && !domUtils.isBody(start) && start.nodeName == "P") {
                        var pre = start.previousSibling;
                        if (pre && pre.nodeType == 1) {
                            var pre = checkIsCludeLink(pre);
                            if (pre && !pre.getAttribute("_href")) {
                                domUtils.remove(pre, true)
                            }
                        }
                    }
                } else {
                    if (keyCode == 32) {
                        if (start.nodeType == 3 && /^\s$/.test(start.nodeValue)) {
                            start = start.previousSibling;
                            if (start && start.nodeName == "A" && !start.getAttribute("_href")) {
                                domUtils.remove(start, true)
                            }
                        }
                    } else {
                        start = domUtils.findParentByTagName(start, "a", true);
                        if (start && !start.getAttribute("_href")) {
                            var bk = rng.createBookmark();
                            domUtils.remove(start, true);
                            rng.moveToBookmark(bk).select(true)
                        }
                    }
                }
            }
        })
    });
    UE.plugins["autoheight"] = function() {
        var me = this;
        me.autoHeightEnabled = me.options.autoHeightEnabled !== false;
        if (!me.autoHeightEnabled) {
            return
        }
        var bakOverflow, lastHeight = 0,
            options = me.options,
            currentHeight, timer;

        function adjustHeight() {
            var me = this;
            clearTimeout(timer);
            if (isFullscreen) {
                return
            }
            if (!me.queryCommandState || me.queryCommandState && me.queryCommandState("source") != 1) {
                timer = setTimeout(function() {
                    var node = me.body.lastChild;
                    while (node && node.nodeType != 1) {
                        node = node.previousSibling
                    }
                    if (node && node.nodeType == 1) {
                        node.style.clear = "both";
                        currentHeight = Math.max(domUtils.getXY(node).y + node.offsetHeight + 25, Math.max(options.minFrameHeight, options.initialFrameHeight));
                        if (currentHeight != lastHeight) {
                            if (currentHeight !== parseInt(me.iframe.parentNode.style.height)) {
                                me.iframe.parentNode.style.height = currentHeight + "px"
                            }
                            me.body.style.height = currentHeight + "px";
                            lastHeight = currentHeight
                        }
                        domUtils.removeStyle(node, "clear")
                    }
                }, 50)
            }
        }
        var isFullscreen;
        me.addListener("fullscreenchanged", function(cmd, f) {
            isFullscreen = f
        });
        me.addListener("destroy", function() {
            me.removeListener("contentchange afterinserthtml keyup mouseup", adjustHeight)
        });
        me.enableAutoHeight = function() {
            var me = this;
            if (!me.autoHeightEnabled) {
                return
            }
            var doc = me.document;
            me.autoHeightEnabled = true;
            bakOverflow = doc.body.style.overflowY;
            doc.body.style.overflowY = "hidden";
            me.addListener("contentchange afterinserthtml keyup mouseup", adjustHeight);
            setTimeout(function() {
                adjustHeight.call(me)
            }, browser.gecko ? 100 : 0);
            me.fireEvent("autoheightchanged", me.autoHeightEnabled)
        };
        me.disableAutoHeight = function() {
            me.body.style.overflowY = bakOverflow || "";
            me.removeListener("contentchange", adjustHeight);
            me.removeListener("keyup", adjustHeight);
            me.removeListener("mouseup", adjustHeight);
            me.autoHeightEnabled = false;
            me.fireEvent("autoheightchanged", me.autoHeightEnabled)
        };
        me.on("setHeight", function() {
            me.disableAutoHeight()
        });
        me.addListener("ready", function() {
            me.enableAutoHeight();
            var timer;
            domUtils.on(browser.ie ? me.body : me.document, browser.webkit ? "dragover" : "drop", function() {
                clearTimeout(timer);
                timer = setTimeout(function() {
                    adjustHeight.call(me)
                }, 100)
            });
            var lastScrollY;
            window.onscroll = function() {
                if (lastScrollY === null) {
                    lastScrollY = this.scrollY
                } else {
                    if (this.scrollY == 0 && lastScrollY != 0) {
                        me.window.scrollTo(0, 0);
                        lastScrollY = null
                    }
                }
            }
        })
    };
    UE.plugins["autofloat"] = function() {
        var me = this,
            lang = me.getLang();
        me.setOpt({
            topOffset: 0
        });
        var optsAutoFloatEnabled = me.options.autoFloatEnabled !== false,
            topOffset = me.options.topOffset;
        if (!optsAutoFloatEnabled) {
            return
        }
        var uiUtils = UE.ui.uiUtils,
            LteIE6 = browser.ie && browser.version <= 6,
            quirks = browser.quirks;

        function checkHasUI() {
            if (!UE.ui) {
                alert(lang.autofloatMsg);
                return 0
            }
            return 1
        }
        function fixIE6FixedPos() {
            var docStyle = document.body.style;
            docStyle.backgroundImage = 'url("about:blank")';
            docStyle.backgroundAttachment = "fixed"
        }
        var bakCssText, placeHolder = document.createElement("div"),
            toolbarBox, orgTop, getPosition, flag = true;

        function setFloating() {
            var toobarBoxPos = domUtils.getXY(toolbarBox),
                origalFloat = domUtils.getComputedStyle(toolbarBox, "position"),
                origalLeft = domUtils.getComputedStyle(toolbarBox, "left");
            toolbarBox.style.width = toolbarBox.offsetWidth + "px";
            toolbarBox.style.zIndex = me.options.zIndex * 1 + 1;
            toolbarBox.parentNode.insertBefore(placeHolder, toolbarBox);
            if (LteIE6 || (quirks && browser.ie)) {
                if (toolbarBox.style.position != "absolute") {
                    toolbarBox.style.position = "absolute"
                }
                toolbarBox.style.top = (document.body.scrollTop || document.documentElement.scrollTop) - orgTop + topOffset + "px"
            } else {
                if (browser.ie7Compat && flag) {
                    flag = false;
                    toolbarBox.style.left = domUtils.getXY(toolbarBox).x - document.documentElement.getBoundingClientRect().left + 2 + "px"
                }
                if (toolbarBox.style.position != "fixed") {
                    toolbarBox.style.position = "fixed";
                    toolbarBox.style.top = topOffset + "px";
                    ((origalFloat == "absolute" || origalFloat == "relative") && parseFloat(origalLeft)) && (toolbarBox.style.left = toobarBoxPos.x + "px")
                }
            }
        }
        function unsetFloating() {
            flag = true;
            if (placeHolder.parentNode) {
                placeHolder.parentNode.removeChild(placeHolder)
            }
            toolbarBox.style.cssText = bakCssText
        }
        function updateFloating() {
            var rect3 = getPosition(me.container);
            var offset = me.options.toolbarTopOffset || 0;
            if (rect3.top < 0 && rect3.bottom - toolbarBox.offsetHeight > offset) {
                setFloating()
            } else {
                unsetFloating()
            }
        }
        var defer_updateFloating = utils.defer(function() {
            updateFloating()
        }, browser.ie ? 200 : 100, true);
        me.addListener("destroy", function() {
            domUtils.un(window, ["scroll", "resize"], updateFloating);
            me.removeListener("keydown", defer_updateFloating)
        });
        me.addListener("ready", function() {
            if (checkHasUI(me)) {
                if (!me.ui) {
                    return
                }
                getPosition = uiUtils.getClientRect;
                toolbarBox = me.ui.getDom("toolbarbox");
                orgTop = getPosition(toolbarBox).top;
                bakCssText = toolbarBox.style.cssText;
                placeHolder.style.height = toolbarBox.offsetHeight + "px";
                if (LteIE6) {
                    fixIE6FixedPos()
                }
                domUtils.on(window, ["scroll", "resize"], updateFloating);
                me.addListener("keydown", defer_updateFloating);
                me.addListener("beforefullscreenchange", function(t, enabled) {
                    if (enabled) {
                        unsetFloating()
                    }
                });
                me.addListener("fullscreenchanged", function(t, enabled) {
                    if (!enabled) {
                        updateFloating()
                    }
                });
                me.addListener("sourcemodechanged", function(t, enabled) {
                    setTimeout(function() {
                        updateFloating()
                    }, 0)
                });
                me.addListener("clearDoc", function() {
                    setTimeout(function() {
                        updateFloating()
                    }, 0)
                })
            }
        })
    };
    UE.plugins["video"] = function() {
        var me = this;
        function creatInsertStr(url, width, height, id, align, classname, type) {
            url = utils.unhtmlForUrl(url);
            align = utils.unhtml(align);
            classname = utils.unhtml(classname);
            width = parseInt(width, 10) || 0;
            height = parseInt(height, 10) || 0;
            var str;
            debugger;
            switch (type) {
                case "image":
                    str = "<img " + (id ? 'id="' + id + '"' : "") + ' width="' + width + '" height="' + height + '" _url="' + url + '" class="' + classname.replace(/\bvideo-js\b/, "") + '"' + ' src="' + me.options.UEDITOR_HOME_URL + 'themes/default/images/spacer.gif" style="background:url(' + me.options.UEDITOR_HOME_URL + "themes/default/images/videologo.gif) no-repeat center center; border:1px solid gray;" + (align ? "float:" + align + ";" : "") + '" />';
                    break;
                case "embed":
                    str = '<embed type="application/x-shockwave-flash" class="' + classname + '" pluginspage="http://www.macromedia.com/go/getflashplayer"' + ' src="' + utils.html(url) + '" width="' + width + '" height="' + height + '"' + (align ? ' style="float:' + align + '"' : "") + ' wmode="transparent" play="true" loop="false" menu="false" allowscriptaccess="never" allowfullscreen="true" >';
                    break;
                case "video":
                    var ext = url.substr(url.lastIndexOf(".") + 1);
                    if (ext == "ogv") {
                        ext = "ogg"
                    }
                // <video class="edui-upload-video
                //     vjs-default-skin video-js" controls="" preload="none" width="420" height="280"
                // src="http://www.ytmp3.cn/down/50274.mp3" data-setup="{}"></video>
                    str = "<video" + (id ? ' id="' + id + '"' : "") + ' class="' + classname + ' video-js" ' + (align ? ' style="float:' + align + '"' : "") + ' controls preload="none" width="' + width + '" height="' + height + '" src="' + url + '" data-setup="{}">' + '</video>';
                    break
            }
            return str
        }
        function switchImgAndVideo(root, img2video) {
            utils.each(root.getNodesByTagName(img2video ? "img" : "embed video"), function(node) {
                var className = node.getAttr("class");
                if (className && className.indexOf("edui-faked-video") != -1) {
                    var html = creatInsertStr(img2video ? node.getAttr("_url") : node.getAttr("src"), node.getAttr("width"), node.getAttr("height"), null, node.getStyle("float") || "", className, img2video ? "video" : "image");
                    node.parentNode.replaceChild(UE.uNode.createElement(html), node)
                }
                if (className && className.indexOf("edui-upload-video") != -1) {
                    var html = creatInsertStr(img2video ? node.getAttr("_url") : node.getAttr("src"), node.getAttr("width"), node.getAttr("height"), null, node.getStyle("float") || "", className, img2video ? "video" : "image");
                    node.parentNode.replaceChild(UE.uNode.createElement(html), node)
                }
            })
        }
        me.addOutputRule(function(root) {
            switchImgAndVideo(root, true)
        });
        me.addInputRule(function(root) {
            switchImgAndVideo(root)
        });
        me.commands["insertvideo"] = {
            execCommand: function(cmd, videoObjs, type) {
                videoObjs = utils.isArray(videoObjs) ? videoObjs : [videoObjs];
                var html = [],
                    id = "tmpVedio",
                    cl;
                for (var i = 0, vi, len = videoObjs.length; i < len; i++) {
                    vi = videoObjs[i];
                    cl = (type == "upload" ? "edui-upload-video video-js vjs-default-skin" : "edui-faked-video");
                    html.push(creatInsertStr(vi.url, vi.width || 420, vi.height || 280, id + i, null, cl, "image"))
                }
                me.execCommand("inserthtml", html.join(""), true);
                var rng = this.selection.getRange();
                for (var i = 0, len = videoObjs.length; i < len; i++) {
                    var img = this.document.getElementById("tmpVedio" + i);
                    domUtils.removeAttributes(img, "id");
                    rng.selectNode(img).select();
                    me.execCommand("imagefloat", videoObjs[i].align)
                }
            },
            queryCommandState: function() {
                var img = me.selection.getRange().getClosedNode(),
                    flag = img && (img.className == "edui-faked-video" || img.className.indexOf("edui-upload-video") != -1);
                return flag ? 1 : 0
            }
        }
    };
    (function() {
        var UETable = UE.UETable = function(table) {
            this.table = table;
            this.indexTable = [];
            this.selectedTds = [];
            this.cellsRange = {};
            this.update(table)
        };
        UETable.removeSelectedClass = function(cells) {
            utils.each(cells, function(cell) {
                domUtils.removeClasses(cell, "selectTdClass")
            })
        };
        UETable.addSelectedClass = function(cells) {
            utils.each(cells, function(cell) {
                domUtils.addClass(cell, "selectTdClass")
            })
        };
        UETable.isEmptyBlock = function(node) {
            var reg = new RegExp(domUtils.fillChar, "g");
            if (node[browser.ie ? "innerText" : "textContent"].replace(/^\s*$/, "").replace(reg, "").length > 0) {
                return 0
            }
            for (var i in dtd.$isNotEmpty) {
                if (dtd.$isNotEmpty.hasOwnProperty(i)) {
                    if (node.getElementsByTagName(i).length) {
                        return 0
                    }
                }
            }
            return 1
        };
        UETable.getWidth = function(cell) {
            if (!cell) {
                return 0
            }
            return parseInt(domUtils.getComputedStyle(cell, "width"), 10)
        };
        UETable.getTableCellAlignState = function(cells) {
            !utils.isArray(cells) && (cells = [cells]);
            var result = {},
                status = ["align", "valign"],
                tempStatus = null,
                isSame = true;
            utils.each(cells, function(cellNode) {
                utils.each(status, function(currentState) {
                    tempStatus = cellNode.getAttribute(currentState);
                    if (!result[currentState] && tempStatus) {
                        result[currentState] = tempStatus
                    } else {
                        if (!result[currentState] || (tempStatus !== result[currentState])) {
                            isSame = false;
                            return false
                        }
                    }
                });
                return isSame
            });
            return isSame ? result : null
        };
        UETable.getTableItemsByRange = function(editor) {
            var start = editor.selection.getStart();
            if (start && start.id && start.id.indexOf("_baidu_bookmark_start_") === 0 && start.nextSibling) {
                start = start.nextSibling
            }
            var cell = start && domUtils.findParentByTagName(start, ["td", "th"], true),
                tr = cell && cell.parentNode,
                caption = start && domUtils.findParentByTagName(start, "caption", true),
                table = caption ? caption.parentNode : tr && tr.parentNode.parentNode;
            return {
                cell: cell,
                tr: tr,
                table: table,
                caption: caption
            }
        };
        UETable.getUETableBySelected = function(editor) {
            var table = UETable.getTableItemsByRange(editor).table;
            if (table && table.ueTable && table.ueTable.selectedTds.length) {
                return table.ueTable
            }
            return null
        };
        UETable.getDefaultValue = function(editor, table) {
            var borderMap = {
                    thin: "0px",
                    medium: "1px",
                    thick: "2px"
                },
                tableBorder, tdPadding, tdBorder, tmpValue;
            if (!table) {
                table = editor.document.createElement("table");
                table.insertRow(0).insertCell(0).innerHTML = "xxx";
                editor.body.appendChild(table);
                var td = table.getElementsByTagName("td")[0];
                tmpValue = domUtils.getComputedStyle(table, "border-left-width");
                tableBorder = parseInt(borderMap[tmpValue] || tmpValue, 10);
                tmpValue = domUtils.getComputedStyle(td, "padding-left");
                tdPadding = parseInt(borderMap[tmpValue] || tmpValue, 10);
                tmpValue = domUtils.getComputedStyle(td, "border-left-width");
                tdBorder = parseInt(borderMap[tmpValue] || tmpValue, 10);
                domUtils.remove(table);
                return {
                    tableBorder: tableBorder,
                    tdPadding: tdPadding,
                    tdBorder: tdBorder
                }
            } else {
                td = table.getElementsByTagName("td")[0];
                tmpValue = domUtils.getComputedStyle(table, "border-left-width");
                tableBorder = parseInt(borderMap[tmpValue] || tmpValue, 10);
                tmpValue = domUtils.getComputedStyle(td, "padding-left");
                tdPadding = parseInt(borderMap[tmpValue] || tmpValue, 10);
                tmpValue = domUtils.getComputedStyle(td, "border-left-width");
                tdBorder = parseInt(borderMap[tmpValue] || tmpValue, 10);
                return {
                    tableBorder: tableBorder,
                    tdPadding: tdPadding,
                    tdBorder: tdBorder
                }
            }
        };
        UETable.getUETable = function(tdOrTable) {
            var tag = tdOrTable.tagName.toLowerCase();
            tdOrTable = (tag == "td" || tag == "th" || tag == "caption") ? domUtils.findParentByTagName(tdOrTable, "table", true) : tdOrTable;
            if (!tdOrTable.ueTable) {
                tdOrTable.ueTable = new UETable(tdOrTable)
            }
            return tdOrTable.ueTable
        };
        UETable.cloneCell = function(cell, ignoreMerge, keepPro) {
            if (!cell || utils.isString(cell)) {
                return this.table.ownerDocument.createElement(cell || "td")
            }
            var flag = domUtils.hasClass(cell, "selectTdClass");
            flag && domUtils.removeClasses(cell, "selectTdClass");
            var tmpCell = cell.cloneNode(true);
            if (ignoreMerge) {
                tmpCell.rowSpan = tmpCell.colSpan = 1
            }!keepPro && domUtils.removeAttributes(tmpCell, "width height");
            !keepPro && domUtils.removeAttributes(tmpCell, "style");
            tmpCell.style.borderLeftStyle = "";
            tmpCell.style.borderTopStyle = "";
            tmpCell.style.borderLeftColor = cell.style.borderRightColor;
            tmpCell.style.borderLeftWidth = cell.style.borderRightWidth;
            tmpCell.style.borderTopColor = cell.style.borderBottomColor;
            tmpCell.style.borderTopWidth = cell.style.borderBottomWidth;
            flag && domUtils.addClass(cell, "selectTdClass");
            return tmpCell
        };
        UETable.prototype = {
            getMaxRows: function() {
                var rows = this.table.rows,
                    maxLen = 1;
                for (var i = 0, row; row = rows[i]; i++) {
                    var currentMax = 1;
                    for (var j = 0, cj; cj = row.cells[j++];) {
                        currentMax = Math.max(cj.rowSpan || 1, currentMax)
                    }
                    maxLen = Math.max(currentMax + i, maxLen)
                }
                return maxLen
            },
            getMaxCols: function() {
                var rows = this.table.rows,
                    maxLen = 0,
                    cellRows = {};
                for (var i = 0, row; row = rows[i]; i++) {
                    var cellsNum = 0;
                    for (var j = 0, cj; cj = row.cells[j++];) {
                        cellsNum += (cj.colSpan || 1);
                        if (cj.rowSpan && cj.rowSpan > 1) {
                            for (var k = 1; k < cj.rowSpan; k++) {
                                if (!cellRows["row_" + (i + k)]) {
                                    cellRows["row_" + (i + k)] = (cj.colSpan || 1)
                                } else {
                                    cellRows["row_" + (i + k)]++
                                }
                            }
                        }
                    }
                    cellsNum += cellRows["row_" + i] || 0;
                    maxLen = Math.max(cellsNum, maxLen)
                }
                return maxLen
            },
            getCellColIndex: function(cell) {},
            getHSideCell: function(cell, right) {
                try {
                    var cellInfo = this.getCellInfo(cell),
                        previewRowIndex, previewColIndex;
                    var len = this.selectedTds.length,
                        range = this.cellsRange;
                    if ((!right && (!len ? !cellInfo.colIndex : !range.beginColIndex)) || (right && (!len ? (cellInfo.colIndex == (this.colsNum - 1)) : (range.endColIndex == this.colsNum - 1)))) {
                        return null
                    }
                    previewRowIndex = !len ? cellInfo.rowIndex : range.beginRowIndex;
                    previewColIndex = !right ? (!len ? (cellInfo.colIndex < 1 ? 0 : (cellInfo.colIndex - 1)) : range.beginColIndex - 1) : (!len ? cellInfo.colIndex + 1 : range.endColIndex + 1);
                    return this.getCell(this.indexTable[previewRowIndex][previewColIndex].rowIndex, this.indexTable[previewRowIndex][previewColIndex].cellIndex)
                } catch (e) {
                    showError(e)
                }
            },
            getTabNextCell: function(cell, preRowIndex) {
                var cellInfo = this.getCellInfo(cell),
                    rowIndex = preRowIndex || cellInfo.rowIndex,
                    colIndex = cellInfo.colIndex + 1 + (cellInfo.colSpan - 1),
                    nextCell;
                try {
                    nextCell = this.getCell(this.indexTable[rowIndex][colIndex].rowIndex, this.indexTable[rowIndex][colIndex].cellIndex)
                } catch (e) {
                    try {
                        rowIndex = rowIndex * 1 + 1;
                        colIndex = 0;
                        nextCell = this.getCell(this.indexTable[rowIndex][colIndex].rowIndex, this.indexTable[rowIndex][colIndex].cellIndex)
                    } catch (e) {}
                }
                return nextCell
            },
            getVSideCell: function(cell, bottom, ignoreRange) {
                try {
                    var cellInfo = this.getCellInfo(cell),
                        nextRowIndex, nextColIndex;
                    var len = this.selectedTds.length && !ignoreRange,
                        range = this.cellsRange;
                    if ((!bottom && (cellInfo.rowIndex == 0)) || (bottom && (!len ? (cellInfo.rowIndex + cellInfo.rowSpan > this.rowsNum - 1) : (range.endRowIndex == this.rowsNum - 1)))) {
                        return null
                    }
                    nextRowIndex = !bottom ? (!len ? cellInfo.rowIndex - 1 : range.beginRowIndex - 1) : (!len ? (cellInfo.rowIndex + cellInfo.rowSpan) : range.endRowIndex + 1);
                    nextColIndex = !len ? cellInfo.colIndex : range.beginColIndex;
                    return this.getCell(this.indexTable[nextRowIndex][nextColIndex].rowIndex, this.indexTable[nextRowIndex][nextColIndex].cellIndex)
                } catch (e) {
                    showError(e)
                }
            },
            getSameEndPosCells: function(cell, xOrY) {
                try {
                    var flag = (xOrY.toLowerCase() === "x"),
                        end = domUtils.getXY(cell)[flag ? "x" : "y"] + cell["offset" + (flag ? "Width" : "Height")],
                        rows = this.table.rows,
                        cells = null,
                        returns = [];
                    for (var i = 0; i < this.rowsNum; i++) {
                        cells = rows[i].cells;
                        for (var j = 0, tmpCell; tmpCell = cells[j++];) {
                            var tmpEnd = domUtils.getXY(tmpCell)[flag ? "x" : "y"] + tmpCell["offset" + (flag ? "Width" : "Height")];
                            if (tmpEnd > end && flag) {
                                break
                            }
                            if (cell == tmpCell || end == tmpEnd) {
                                if (tmpCell[flag ? "colSpan" : "rowSpan"] == 1) {
                                    returns.push(tmpCell)
                                }
                                if (flag) {
                                    break
                                }
                            }
                        }
                    }
                    return returns
                } catch (e) {
                    showError(e)
                }
            },
            setCellContent: function(cell, content) {
                cell.innerHTML = content || (browser.ie ? domUtils.fillChar : "<br />")
            },
            cloneCell: UETable.cloneCell,
            getSameStartPosXCells: function(cell) {
                try {
                    var start = domUtils.getXY(cell).x + cell.offsetWidth,
                        rows = this.table.rows,
                        cells, returns = [];
                    for (var i = 0; i < this.rowsNum; i++) {
                        cells = rows[i].cells;
                        for (var j = 0, tmpCell; tmpCell = cells[j++];) {
                            var tmpStart = domUtils.getXY(tmpCell).x;
                            if (tmpStart > start) {
                                break
                            }
                            if (tmpStart == start && tmpCell.colSpan == 1) {
                                returns.push(tmpCell);
                                break
                            }
                        }
                    }
                    return returns
                } catch (e) {
                    showError(e)
                }
            },
            update: function(table) {
                this.table = table || this.table;
                this.selectedTds = [];
                this.cellsRange = {};
                this.indexTable = [];
                var rows = this.table.rows,
                    rowsNum = this.getMaxRows(),
                    dNum = rowsNum - rows.length,
                    colsNum = this.getMaxCols();
                while (dNum--) {
                    this.table.insertRow(rows.length)
                }
                this.rowsNum = rowsNum;
                this.colsNum = colsNum;
                for (var i = 0, len = rows.length; i < len; i++) {
                    this.indexTable[i] = new Array(colsNum)
                }
                for (var rowIndex = 0, row; row = rows[rowIndex]; rowIndex++) {
                    for (var cellIndex = 0, cell, cells = row.cells; cell = cells[cellIndex]; cellIndex++) {
                        if (cell.rowSpan > rowsNum) {
                            cell.rowSpan = rowsNum
                        }
                        var colIndex = cellIndex,
                            rowSpan = cell.rowSpan || 1,
                            colSpan = cell.colSpan || 1;
                        while (this.indexTable[rowIndex][colIndex]) {
                            colIndex++
                        }
                        for (var j = 0; j < rowSpan; j++) {
                            for (var k = 0; k < colSpan; k++) {
                                this.indexTable[rowIndex + j][colIndex + k] = {
                                    rowIndex: rowIndex,
                                    cellIndex: cellIndex,
                                    colIndex: colIndex,
                                    rowSpan: rowSpan,
                                    colSpan: colSpan
                                }
                            }
                        }
                    }
                }
                for (j = 0; j < rowsNum; j++) {
                    for (k = 0; k < colsNum; k++) {
                        if (this.indexTable[j][k] === undefined) {
                            row = rows[j];
                            cell = row.cells[row.cells.length - 1];
                            cell = cell ? cell.cloneNode(true) : this.table.ownerDocument.createElement("td");
                            this.setCellContent(cell);
                            if (cell.colSpan !== 1) {
                                cell.colSpan = 1
                            }
                            if (cell.rowSpan !== 1) {
                                cell.rowSpan = 1
                            }
                            row.appendChild(cell);
                            this.indexTable[j][k] = {
                                rowIndex: j,
                                cellIndex: cell.cellIndex,
                                colIndex: k,
                                rowSpan: 1,
                                colSpan: 1
                            }
                        }
                    }
                }
                var tds = domUtils.getElementsByTagName(this.table, "td"),
                    selectTds = [];
                utils.each(tds, function(td) {
                    if (domUtils.hasClass(td, "selectTdClass")) {
                        selectTds.push(td)
                    }
                });
                if (selectTds.length) {
                    var start = selectTds[0],
                        end = selectTds[selectTds.length - 1],
                        startInfo = this.getCellInfo(start),
                        endInfo = this.getCellInfo(end);
                    this.selectedTds = selectTds;
                    this.cellsRange = {
                        beginRowIndex: startInfo.rowIndex,
                        beginColIndex: startInfo.colIndex,
                        endRowIndex: endInfo.rowIndex + endInfo.rowSpan - 1,
                        endColIndex: endInfo.colIndex + endInfo.colSpan - 1
                    }
                }
                if (!domUtils.hasClass(this.table.rows[0], "firstRow")) {
                    domUtils.addClass(this.table.rows[0], "firstRow");
                    for (var i = 1; i < this.table.rows.length; i++) {
                        domUtils.removeClasses(this.table.rows[i], "firstRow")
                    }
                }
            },
            getCellInfo: function(cell) {
                if (!cell) {
                    return
                }
                var cellIndex = cell.cellIndex,
                    rowIndex = cell.parentNode.rowIndex,
                    rowInfo = this.indexTable[rowIndex],
                    numCols = this.colsNum;
                for (var colIndex = cellIndex; colIndex < numCols; colIndex++) {
                    var cellInfo = rowInfo[colIndex];
                    if (cellInfo.rowIndex === rowIndex && cellInfo.cellIndex === cellIndex) {
                        return cellInfo
                    }
                }
            },
            getCell: function(rowIndex, cellIndex) {
                return rowIndex < this.rowsNum && this.table.rows[rowIndex].cells[cellIndex] || null
            },
            deleteCell: function(cell, rowIndex) {
                rowIndex = typeof rowIndex == "number" ? rowIndex : cell.parentNode.rowIndex;
                var row = this.table.rows[rowIndex];
                row.deleteCell(cell.cellIndex)
            },
            getCellsRange: function(cellA, cellB) {
                function checkRange(beginRowIndex, beginColIndex, endRowIndex, endColIndex) {
                    var tmpBeginRowIndex = beginRowIndex,
                        tmpBeginColIndex = beginColIndex,
                        tmpEndRowIndex = endRowIndex,
                        tmpEndColIndex = endColIndex,
                        cellInfo, colIndex, rowIndex;
                    if (beginRowIndex > 0) {
                        for (colIndex = beginColIndex; colIndex < endColIndex; colIndex++) {
                            cellInfo = me.indexTable[beginRowIndex][colIndex];
                            rowIndex = cellInfo.rowIndex;
                            if (rowIndex < beginRowIndex) {
                                tmpBeginRowIndex = Math.min(rowIndex, tmpBeginRowIndex)
                            }
                        }
                    }
                    if (endColIndex < me.colsNum) {
                        for (rowIndex = beginRowIndex; rowIndex < endRowIndex; rowIndex++) {
                            cellInfo = me.indexTable[rowIndex][endColIndex];
                            colIndex = cellInfo.colIndex + cellInfo.colSpan - 1;
                            if (colIndex > endColIndex) {
                                tmpEndColIndex = Math.max(colIndex, tmpEndColIndex)
                            }
                        }
                    }
                    if (endRowIndex < me.rowsNum) {
                        for (colIndex = beginColIndex; colIndex < endColIndex; colIndex++) {
                            cellInfo = me.indexTable[endRowIndex][colIndex];
                            rowIndex = cellInfo.rowIndex + cellInfo.rowSpan - 1;
                            if (rowIndex > endRowIndex) {
                                tmpEndRowIndex = Math.max(rowIndex, tmpEndRowIndex)
                            }
                        }
                    }
                    if (beginColIndex > 0) {
                        for (rowIndex = beginRowIndex; rowIndex < endRowIndex; rowIndex++) {
                            cellInfo = me.indexTable[rowIndex][beginColIndex];
                            colIndex = cellInfo.colIndex;
                            if (colIndex < beginColIndex) {
                                tmpBeginColIndex = Math.min(cellInfo.colIndex, tmpBeginColIndex)
                            }
                        }
                    }
                    if (tmpBeginRowIndex != beginRowIndex || tmpBeginColIndex != beginColIndex || tmpEndRowIndex != endRowIndex || tmpEndColIndex != endColIndex) {
                        return checkRange(tmpBeginRowIndex, tmpBeginColIndex, tmpEndRowIndex, tmpEndColIndex)
                    } else {
                        return {
                            beginRowIndex: beginRowIndex,
                            beginColIndex: beginColIndex,
                            endRowIndex: endRowIndex,
                            endColIndex: endColIndex
                        }
                    }
                }
                try {
                    var me = this,
                        cellAInfo = me.getCellInfo(cellA);
                    if (cellA === cellB) {
                        return {
                            beginRowIndex: cellAInfo.rowIndex,
                            beginColIndex: cellAInfo.colIndex,
                            endRowIndex: cellAInfo.rowIndex + cellAInfo.rowSpan - 1,
                            endColIndex: cellAInfo.colIndex + cellAInfo.colSpan - 1
                        }
                    }
                    var cellBInfo = me.getCellInfo(cellB);
                    var beginRowIndex = Math.min(cellAInfo.rowIndex, cellBInfo.rowIndex),
                        beginColIndex = Math.min(cellAInfo.colIndex, cellBInfo.colIndex),
                        endRowIndex = Math.max(cellAInfo.rowIndex + cellAInfo.rowSpan - 1, cellBInfo.rowIndex + cellBInfo.rowSpan - 1),
                        endColIndex = Math.max(cellAInfo.colIndex + cellAInfo.colSpan - 1, cellBInfo.colIndex + cellBInfo.colSpan - 1);
                    return checkRange(beginRowIndex, beginColIndex, endRowIndex, endColIndex)
                } catch (e) {}
            },
            getCells: function(range) {
                this.clearSelected();
                var beginRowIndex = range.beginRowIndex,
                    beginColIndex = range.beginColIndex,
                    endRowIndex = range.endRowIndex,
                    endColIndex = range.endColIndex,
                    cellInfo, rowIndex, colIndex, tdHash = {},
                    returnTds = [];
                for (var i = beginRowIndex; i <= endRowIndex; i++) {
                    for (var j = beginColIndex; j <= endColIndex; j++) {
                        cellInfo = this.indexTable[i][j];
                        rowIndex = cellInfo.rowIndex;
                        colIndex = cellInfo.colIndex;
                        var key = rowIndex + "|" + colIndex;
                        if (tdHash[key]) {
                            continue
                        }
                        tdHash[key] = 1;
                        if (rowIndex < i || colIndex < j || rowIndex + cellInfo.rowSpan - 1 > endRowIndex || colIndex + cellInfo.colSpan - 1 > endColIndex) {
                            return null
                        }
                        returnTds.push(this.getCell(rowIndex, cellInfo.cellIndex))
                    }
                }
                return returnTds
            },
            clearSelected: function() {
                UETable.removeSelectedClass(this.selectedTds);
                this.selectedTds = [];
                this.cellsRange = {}
            },
            setSelected: function(range) {
                var cells = this.getCells(range);
                UETable.addSelectedClass(cells);
                this.selectedTds = cells;
                this.cellsRange = range
            },
            isFullRow: function() {
                var range = this.cellsRange;
                return (range.endColIndex - range.beginColIndex + 1) == this.colsNum
            },
            isFullCol: function() {
                var range = this.cellsRange,
                    table = this.table,
                    ths = table.getElementsByTagName("th"),
                    rows = range.endRowIndex - range.beginRowIndex + 1;
                return !ths.length ? rows == this.rowsNum : rows == this.rowsNum || (rows == this.rowsNum - 1)
            },
            getNextCell: function(cell, bottom, ignoreRange) {
                try {
                    var cellInfo = this.getCellInfo(cell),
                        nextRowIndex, nextColIndex;
                    var len = this.selectedTds.length && !ignoreRange,
                        range = this.cellsRange;
                    if ((!bottom && (cellInfo.rowIndex == 0)) || (bottom && (!len ? (cellInfo.rowIndex + cellInfo.rowSpan > this.rowsNum - 1) : (range.endRowIndex == this.rowsNum - 1)))) {
                        return null
                    }
                    nextRowIndex = !bottom ? (!len ? cellInfo.rowIndex - 1 : range.beginRowIndex - 1) : (!len ? (cellInfo.rowIndex + cellInfo.rowSpan) : range.endRowIndex + 1);
                    nextColIndex = !len ? cellInfo.colIndex : range.beginColIndex;
                    return this.getCell(this.indexTable[nextRowIndex][nextColIndex].rowIndex, this.indexTable[nextRowIndex][nextColIndex].cellIndex)
                } catch (e) {
                    showError(e)
                }
            },
            getPreviewCell: function(cell, top) {
                try {
                    var cellInfo = this.getCellInfo(cell),
                        previewRowIndex, previewColIndex;
                    var len = this.selectedTds.length,
                        range = this.cellsRange;
                    if ((!top && (!len ? !cellInfo.colIndex : !range.beginColIndex)) || (top && (!len ? (cellInfo.rowIndex > (this.colsNum - 1)) : (range.endColIndex == this.colsNum - 1)))) {
                        return null
                    }
                    previewRowIndex = !top ? (!len ? cellInfo.rowIndex : range.beginRowIndex) : (!len ? (cellInfo.rowIndex < 1 ? 0 : (cellInfo.rowIndex - 1)) : range.beginRowIndex);
                    previewColIndex = !top ? (!len ? (cellInfo.colIndex < 1 ? 0 : (cellInfo.colIndex - 1)) : range.beginColIndex - 1) : (!len ? cellInfo.colIndex : range.endColIndex + 1);
                    return this.getCell(this.indexTable[previewRowIndex][previewColIndex].rowIndex, this.indexTable[previewRowIndex][previewColIndex].cellIndex)
                } catch (e) {
                    showError(e)
                }
            },
            moveContent: function(cellTo, cellFrom) {
                if (UETable.isEmptyBlock(cellFrom)) {
                    return
                }
                if (UETable.isEmptyBlock(cellTo)) {
                    cellTo.innerHTML = cellFrom.innerHTML;
                    return
                }
                var child = cellTo.lastChild;
                if (child.nodeType == 3 || !dtd.$block[child.tagName]) {
                    cellTo.appendChild(cellTo.ownerDocument.createElement("br"))
                }
                while (child = cellFrom.firstChild) {
                    cellTo.appendChild(child)
                }
            },
            mergeRight: function(cell) {
                var cellInfo = this.getCellInfo(cell),
                    rightColIndex = cellInfo.colIndex + cellInfo.colSpan,
                    rightCellInfo = this.indexTable[cellInfo.rowIndex][rightColIndex],
                    rightCell = this.getCell(rightCellInfo.rowIndex, rightCellInfo.cellIndex);
                cell.colSpan = cellInfo.colSpan + rightCellInfo.colSpan;
                cell.removeAttribute("width");
                this.moveContent(cell, rightCell);
                this.deleteCell(rightCell, rightCellInfo.rowIndex);
                this.update()
            },
            mergeDown: function(cell) {
                var cellInfo = this.getCellInfo(cell),
                    downRowIndex = cellInfo.rowIndex + cellInfo.rowSpan,
                    downCellInfo = this.indexTable[downRowIndex][cellInfo.colIndex],
                    downCell = this.getCell(downCellInfo.rowIndex, downCellInfo.cellIndex);
                cell.rowSpan = cellInfo.rowSpan + downCellInfo.rowSpan;
                cell.removeAttribute("height");
                this.moveContent(cell, downCell);
                this.deleteCell(downCell, downCellInfo.rowIndex);
                this.update()
            },
            mergeRange: function() {
                var range = this.cellsRange,
                    leftTopCell = this.getCell(range.beginRowIndex, this.indexTable[range.beginRowIndex][range.beginColIndex].cellIndex);
                if (leftTopCell.tagName == "TH" && range.endRowIndex !== range.beginRowIndex) {
                    var index = this.indexTable,
                        info = this.getCellInfo(leftTopCell);
                    leftTopCell = this.getCell(1, index[1][info.colIndex].cellIndex);
                    range = this.getCellsRange(leftTopCell, this.getCell(index[this.rowsNum - 1][info.colIndex].rowIndex, index[this.rowsNum - 1][info.colIndex].cellIndex))
                }
                var cells = this.getCells(range);
                for (var i = 0, ci; ci = cells[i++];) {
                    if (ci !== leftTopCell) {
                        this.moveContent(leftTopCell, ci);
                        this.deleteCell(ci)
                    }
                }
                leftTopCell.rowSpan = range.endRowIndex - range.beginRowIndex + 1;
                leftTopCell.rowSpan > 1 && leftTopCell.removeAttribute("height");
                leftTopCell.colSpan = range.endColIndex - range.beginColIndex + 1;
                leftTopCell.colSpan > 1 && leftTopCell.removeAttribute("width");
                if (leftTopCell.rowSpan == this.rowsNum && leftTopCell.colSpan != 1) {
                    leftTopCell.colSpan = 1
                }
                if (leftTopCell.colSpan == this.colsNum && leftTopCell.rowSpan != 1) {
                    var rowIndex = leftTopCell.parentNode.rowIndex;
                    if (this.table.deleteRow) {
                        for (var i = rowIndex + 1, curIndex = rowIndex + 1, len = leftTopCell.rowSpan; i < len; i++) {
                            this.table.deleteRow(curIndex)
                        }
                    } else {
                        for (var i = 0, len = leftTopCell.rowSpan - 1; i < len; i++) {
                            var row = this.table.rows[rowIndex + 1];
                            row.parentNode.removeChild(row)
                        }
                    }
                    leftTopCell.rowSpan = 1
                }
                this.update()
            },
            insertRow: function(rowIndex, sourceCell) {
                var numCols = this.colsNum,
                    table = this.table,
                    row = table.insertRow(rowIndex),
                    cell, isInsertTitle = typeof sourceCell == "string" && sourceCell.toUpperCase() == "TH";

                function replaceTdToTh(colIndex, cell, tableRow) {
                    if (colIndex == 0) {
                        var tr = tableRow.nextSibling || tableRow.previousSibling,
                            th = tr.cells[colIndex];
                        if (th.tagName == "TH") {
                            th = cell.ownerDocument.createElement("th");
                            th.appendChild(cell.firstChild);
                            tableRow.insertBefore(th, cell);
                            domUtils.remove(cell)
                        }
                    } else {
                        if (cell.tagName == "TH") {
                            var td = cell.ownerDocument.createElement("td");
                            td.appendChild(cell.firstChild);
                            tableRow.insertBefore(td, cell);
                            domUtils.remove(cell)
                        }
                    }
                }
                if (rowIndex == 0 || rowIndex == this.rowsNum) {
                    for (var colIndex = 0; colIndex < numCols; colIndex++) {
                        cell = this.cloneCell(sourceCell, true);
                        this.setCellContent(cell);
                        cell.getAttribute("vAlign") && cell.setAttribute("vAlign", cell.getAttribute("vAlign"));
                        row.appendChild(cell);
                        if (!isInsertTitle) {
                            replaceTdToTh(colIndex, cell, row)
                        }
                    }
                } else {
                    var infoRow = this.indexTable[rowIndex],
                        cellIndex = 0;
                    for (colIndex = 0; colIndex < numCols; colIndex++) {
                        var cellInfo = infoRow[colIndex];
                        if (cellInfo.rowIndex < rowIndex) {
                            cell = this.getCell(cellInfo.rowIndex, cellInfo.cellIndex);
                            cell.rowSpan = cellInfo.rowSpan + 1
                        } else {
                            cell = this.cloneCell(sourceCell, true);
                            this.setCellContent(cell);
                            row.appendChild(cell)
                        }
                        if (!isInsertTitle) {
                            replaceTdToTh(colIndex, cell, row)
                        }
                    }
                }
                this.update();
                return row
            },
            deleteRow: function(rowIndex) {
                var row = this.table.rows[rowIndex],
                    infoRow = this.indexTable[rowIndex],
                    colsNum = this.colsNum,
                    count = 0;
                for (var colIndex = 0; colIndex < colsNum;) {
                    var cellInfo = infoRow[colIndex],
                        cell = this.getCell(cellInfo.rowIndex, cellInfo.cellIndex);
                    if (cell.rowSpan > 1) {
                        if (cellInfo.rowIndex == rowIndex) {
                            var clone = cell.cloneNode(true);
                            clone.rowSpan = cell.rowSpan - 1;
                            clone.innerHTML = "";
                            cell.rowSpan = 1;
                            var nextRowIndex = rowIndex + 1,
                                nextRow = this.table.rows[nextRowIndex],
                                insertCellIndex, preMerged = this.getPreviewMergedCellsNum(nextRowIndex, colIndex) - count;
                            if (preMerged < colIndex) {
                                insertCellIndex = colIndex - preMerged - 1;
                                domUtils.insertAfter(nextRow.cells[insertCellIndex], clone)
                            } else {
                                if (nextRow.cells.length) {
                                    nextRow.insertBefore(clone, nextRow.cells[0])
                                }
                            }
                            count += 1
                        }
                    }
                    colIndex += cell.colSpan || 1
                }
                var deleteTds = [],
                    cacheMap = {};
                for (colIndex = 0; colIndex < colsNum; colIndex++) {
                    var tmpRowIndex = infoRow[colIndex].rowIndex,
                        tmpCellIndex = infoRow[colIndex].cellIndex,
                        key = tmpRowIndex + "_" + tmpCellIndex;
                    if (cacheMap[key]) {
                        continue
                    }
                    cacheMap[key] = 1;
                    cell = this.getCell(tmpRowIndex, tmpCellIndex);
                    deleteTds.push(cell)
                }
                var mergeTds = [];
                utils.each(deleteTds, function(td) {
                    if (td.rowSpan == 1) {
                        td.parentNode.removeChild(td)
                    } else {
                        mergeTds.push(td)
                    }
                });
                utils.each(mergeTds, function(td) {
                    td.rowSpan--
                });
                row.parentNode.removeChild(row);
                this.update()
            },
            insertCol: function(colIndex, sourceCell, defaultValue) {
                var rowsNum = this.rowsNum,
                    rowIndex = 0,
                    tableRow, cell, backWidth = parseInt((this.table.offsetWidth - (this.colsNum + 1) * 20 - (this.colsNum + 1)) / (this.colsNum + 1), 10),
                    isInsertTitleCol = typeof sourceCell == "string" && sourceCell.toUpperCase() == "TH";

                function replaceTdToTh(rowIndex, cell, tableRow) {
                    if (rowIndex == 0) {
                        var th = cell.nextSibling || cell.previousSibling;
                        if (th.tagName == "TH") {
                            th = cell.ownerDocument.createElement("th");
                            th.appendChild(cell.firstChild);
                            tableRow.insertBefore(th, cell);
                            domUtils.remove(cell)
                        }
                    } else {
                        if (cell.tagName == "TH") {
                            var td = cell.ownerDocument.createElement("td");
                            td.appendChild(cell.firstChild);
                            tableRow.insertBefore(td, cell);
                            domUtils.remove(cell)
                        }
                    }
                }
                var preCell;
                if (colIndex == 0 || colIndex == this.colsNum) {
                    for (; rowIndex < rowsNum; rowIndex++) {
                        tableRow = this.table.rows[rowIndex];
                        preCell = tableRow.cells[colIndex == 0 ? colIndex : tableRow.cells.length];
                        cell = this.cloneCell(sourceCell, true);
                        this.setCellContent(cell);
                        cell.setAttribute("vAlign", cell.getAttribute("vAlign"));
                        preCell && cell.setAttribute("width", preCell.getAttribute("width"));
                        if (!colIndex) {
                            tableRow.insertBefore(cell, tableRow.cells[0])
                        } else {
                            domUtils.insertAfter(tableRow.cells[tableRow.cells.length - 1], cell)
                        }
                        if (!isInsertTitleCol) {
                            replaceTdToTh(rowIndex, cell, tableRow)
                        }
                    }
                } else {
                    for (; rowIndex < rowsNum; rowIndex++) {
                        var cellInfo = this.indexTable[rowIndex][colIndex];
                        if (cellInfo.colIndex < colIndex) {
                            cell = this.getCell(cellInfo.rowIndex, cellInfo.cellIndex);
                            cell.colSpan = cellInfo.colSpan + 1
                        } else {
                            tableRow = this.table.rows[rowIndex];
                            preCell = tableRow.cells[cellInfo.cellIndex];
                            cell = this.cloneCell(sourceCell, true);
                            this.setCellContent(cell);
                            cell.setAttribute("vAlign", cell.getAttribute("vAlign"));
                            preCell && cell.setAttribute("width", preCell.getAttribute("width"));
                            preCell ? tableRow.insertBefore(cell, preCell) : tableRow.appendChild(cell)
                        }
                        if (!isInsertTitleCol) {
                            replaceTdToTh(rowIndex, cell, tableRow)
                        }
                    }
                }
                this.update();
                this.updateWidth(backWidth, defaultValue || {
                    tdPadding: 10,
                    tdBorder: 1
                })
            },
            updateWidth: function(width, defaultValue) {
                var table = this.table,
                    tmpWidth = UETable.getWidth(table) - defaultValue.tdPadding * 2 - defaultValue.tdBorder + width;
                if (tmpWidth < table.ownerDocument.body.offsetWidth) {
                    table.setAttribute("width", tmpWidth);
                    return
                }
                var tds = domUtils.getElementsByTagName(this.table, "td th");
                utils.each(tds, function(td) {
                    td.setAttribute("width", width)
                })
            },
            deleteCol: function(colIndex) {
                var indexTable = this.indexTable,
                    tableRows = this.table.rows,
                    backTableWidth = this.table.getAttribute("width"),
                    backTdWidth = 0,
                    rowsNum = this.rowsNum,
                    cacheMap = {};
                for (var rowIndex = 0; rowIndex < rowsNum;) {
                    var infoRow = indexTable[rowIndex],
                        cellInfo = infoRow[colIndex],
                        key = cellInfo.rowIndex + "_" + cellInfo.colIndex;
                    if (cacheMap[key]) {
                        continue
                    }
                    cacheMap[key] = 1;
                    var cell = this.getCell(cellInfo.rowIndex, cellInfo.cellIndex);
                    if (!backTdWidth) {
                        backTdWidth = cell && parseInt(cell.offsetWidth / cell.colSpan, 10).toFixed(0)
                    }
                    if (cell.colSpan > 1) {
                        cell.colSpan--
                    } else {
                        tableRows[rowIndex].deleteCell(cellInfo.cellIndex)
                    }
                    rowIndex += cellInfo.rowSpan || 1
                }
                this.table.setAttribute("width", backTableWidth - backTdWidth);
                this.update()
            },
            splitToCells: function(cell) {
                var me = this,
                    cells = this.splitToRows(cell);
                utils.each(cells, function(cell) {
                    me.splitToCols(cell)
                })
            },
            splitToRows: function(cell) {
                var cellInfo = this.getCellInfo(cell),
                    rowIndex = cellInfo.rowIndex,
                    colIndex = cellInfo.colIndex,
                    results = [];
                cell.rowSpan = 1;
                results.push(cell);
                for (var i = rowIndex, endRow = rowIndex + cellInfo.rowSpan; i < endRow; i++) {
                    if (i == rowIndex) {
                        continue
                    }
                    var tableRow = this.table.rows[i],
                        tmpCell = tableRow.insertCell(colIndex - this.getPreviewMergedCellsNum(i, colIndex));
                    tmpCell.colSpan = cellInfo.colSpan;
                    this.setCellContent(tmpCell);
                    tmpCell.setAttribute("vAlign", cell.getAttribute("vAlign"));
                    tmpCell.setAttribute("align", cell.getAttribute("align"));
                    if (cell.style.cssText) {
                        tmpCell.style.cssText = cell.style.cssText
                    }
                    results.push(tmpCell)
                }
                this.update();
                return results
            },
            getPreviewMergedCellsNum: function(rowIndex, colIndex) {
                var indexRow = this.indexTable[rowIndex],
                    num = 0;
                for (var i = 0; i < colIndex;) {
                    var colSpan = indexRow[i].colSpan,
                        tmpRowIndex = indexRow[i].rowIndex;
                    num += (colSpan - (tmpRowIndex == rowIndex ? 1 : 0));
                    i += colSpan
                }
                return num
            },
            splitToCols: function(cell) {
                var backWidth = (cell.offsetWidth / cell.colSpan - 22).toFixed(0),
                    cellInfo = this.getCellInfo(cell),
                    rowIndex = cellInfo.rowIndex,
                    colIndex = cellInfo.colIndex,
                    results = [];
                cell.colSpan = 1;
                cell.setAttribute("width", backWidth);
                results.push(cell);
                for (var j = colIndex, endCol = colIndex + cellInfo.colSpan; j < endCol; j++) {
                    if (j == colIndex) {
                        continue
                    }
                    var tableRow = this.table.rows[rowIndex],
                        tmpCell = tableRow.insertCell(this.indexTable[rowIndex][j].cellIndex + 1);
                    tmpCell.rowSpan = cellInfo.rowSpan;
                    this.setCellContent(tmpCell);
                    tmpCell.setAttribute("vAlign", cell.getAttribute("vAlign"));
                    tmpCell.setAttribute("align", cell.getAttribute("align"));
                    tmpCell.setAttribute("width", backWidth);
                    if (cell.style.cssText) {
                        tmpCell.style.cssText = cell.style.cssText
                    }
                    if (cell.tagName == "TH") {
                        var th = cell.ownerDocument.createElement("th");
                        th.appendChild(tmpCell.firstChild);
                        th.setAttribute("vAlign", cell.getAttribute("vAlign"));
                        th.rowSpan = tmpCell.rowSpan;
                        tableRow.insertBefore(th, tmpCell);
                        domUtils.remove(tmpCell)
                    }
                    results.push(tmpCell)
                }
                this.update();
                return results
            },
            isLastCell: function(cell, rowsNum, colsNum) {
                rowsNum = rowsNum || this.rowsNum;
                colsNum = colsNum || this.colsNum;
                var cellInfo = this.getCellInfo(cell);
                return ((cellInfo.rowIndex + cellInfo.rowSpan) == rowsNum) && ((cellInfo.colIndex + cellInfo.colSpan) == colsNum)
            },
            getLastCell: function(cells) {
                cells = cells || this.table.getElementsByTagName("td");
                var firstInfo = this.getCellInfo(cells[0]);
                var me = this,
                    last = cells[0],
                    tr = last.parentNode,
                    cellsNum = 0,
                    cols = 0,
                    rows;
                utils.each(cells, function(cell) {
                    if (cell.parentNode == tr) {
                        cols += cell.colSpan || 1
                    }
                    cellsNum += cell.rowSpan * cell.colSpan || 1
                });
                rows = cellsNum / cols;
                utils.each(cells, function(cell) {
                    if (me.isLastCell(cell, rows, cols)) {
                        last = cell;
                        return false
                    }
                });
                return last
            },
            selectRow: function(rowIndex) {
                var indexRow = this.indexTable[rowIndex],
                    start = this.getCell(indexRow[0].rowIndex, indexRow[0].cellIndex),
                    end = this.getCell(indexRow[this.colsNum - 1].rowIndex, indexRow[this.colsNum - 1].cellIndex),
                    range = this.getCellsRange(start, end);
                this.setSelected(range)
            },
            selectTable: function() {
                var tds = this.table.getElementsByTagName("td"),
                    range = this.getCellsRange(tds[0], tds[tds.length - 1]);
                this.setSelected(range)
            },
            setBackground: function(cells, value) {
                if (typeof value === "string") {
                    utils.each(cells, function(cell) {
                        cell.style.backgroundColor = value
                    })
                } else {
                    if (typeof value === "object") {
                        value = utils.extend({
                            repeat: true,
                            colorList: ["#ddd", "#fff"]
                        }, value);
                        var rowIndex = this.getCellInfo(cells[0]).rowIndex,
                            count = 0,
                            colors = value.colorList,
                            getColor = function(list, index, repeat) {
                                return list[index] ? list[index] : repeat ? list[index % list.length] : ""
                            };
                        for (var i = 0, cell; cell = cells[i++];) {
                            var cellInfo = this.getCellInfo(cell);
                            cell.style.backgroundColor = getColor(colors, ((rowIndex + count) == cellInfo.rowIndex) ? count : ++count, value.repeat)
                        }
                    }
                }
            },
            removeBackground: function(cells) {
                utils.each(cells, function(cell) {
                    cell.style.backgroundColor = ""
                })
            }
        };

        function showError(e) {}
    })();
    (function() {
        var UT = UE.UETable,
            getTableItemsByRange = function(editor) {
                return UT.getTableItemsByRange(editor)
            },
            getUETableBySelected = function(editor) {
                return UT.getUETableBySelected(editor)
            },
            getDefaultValue = function(editor, table) {
                return UT.getDefaultValue(editor, table)
            },
            getUETable = function(tdOrTable) {
                return UT.getUETable(tdOrTable)
            };
        UE.commands["inserttable"] = {
            queryCommandState: function() {
                return getTableItemsByRange(this).table ? -1 : 0
            },
            execCommand: function(cmd, opt) {
                function createTable(opt, tdWidth) {
                    var html = [],
                        rowsNum = opt.numRows,
                        colsNum = opt.numCols;
                    for (var r = 0; r < rowsNum; r++) {
                        html.push("<tr" + (r == 0 ? ' class="firstRow"' : "") + ">");
                        for (var c = 0; c < colsNum; c++) {
                            html.push('<td width="' + tdWidth + '"  vAlign="' + opt.tdvalign + '" >' + (browser.ie && browser.version < 11 ? domUtils.fillChar : "<br/>") + "</td>")
                        }
                        html.push("</tr>")
                    }
                    return "<table><tbody>" + html.join("") + "</tbody></table>"
                }
                if (!opt) {
                    opt = utils.extend({}, {
                        numCols: this.options.defaultCols,
                        numRows: this.options.defaultRows,
                        tdvalign: this.options.tdvalign
                    })
                }
                var me = this;
                var range = this.selection.getRange(),
                    start = range.startContainer,
                    firstParentBlock = domUtils.findParent(start, function(node) {
                        return domUtils.isBlockElm(node)
                    }, true) || me.body;
                var defaultValue = getDefaultValue(me),
                    tableWidth = firstParentBlock.offsetWidth,
                    tdWidth = Math.floor(tableWidth / opt.numCols - defaultValue.tdPadding * 2 - defaultValue.tdBorder);
                !opt.tdvalign && (opt.tdvalign = me.options.tdvalign);
                me.execCommand("inserthtml", createTable(opt, tdWidth))
            }
        };
        UE.commands["insertparagraphbeforetable"] = {
            queryCommandState: function() {
                return getTableItemsByRange(this).cell ? 0 : -1
            },
            execCommand: function() {
                var table = getTableItemsByRange(this).table;
                if (table) {
                    var p = this.document.createElement("p");
                    p.innerHTML = browser.ie ? "&nbsp;" : "<br />";
                    table.parentNode.insertBefore(p, table);
                    this.selection.getRange().setStart(p, 0).setCursor()
                }
            }
        };
        UE.commands["deletetable"] = {
            queryCommandState: function() {
                var rng = this.selection.getRange();
                return domUtils.findParentByTagName(rng.startContainer, "table", true) ? 0 : -1
            },
            execCommand: function(cmd, table) {
                var rng = this.selection.getRange();
                table = table || domUtils.findParentByTagName(rng.startContainer, "table", true);
                if (table) {
                    var next = table.nextSibling;
                    if (!next) {
                        next = domUtils.createElement(this.document, "p", {
                            "innerHTML": browser.ie ? domUtils.fillChar : "<br/>"
                        });
                        table.parentNode.insertBefore(next, table)
                    }
                    domUtils.remove(table);
                    rng = this.selection.getRange();
                    if (next.nodeType == 3) {
                        rng.setStartBefore(next)
                    } else {
                        rng.setStart(next, 0)
                    }
                    rng.setCursor(false, true);
                    this.fireEvent("tablehasdeleted")
                }
            }
        };
        UE.commands["cellalign"] = {
            queryCommandState: function() {
                return getSelectedArr(this).length ? 0 : -1
            },
            execCommand: function(cmd, align) {
                var selectedTds = getSelectedArr(this);
                if (selectedTds.length) {
                    for (var i = 0, ci; ci = selectedTds[i++];) {
                        ci.setAttribute("align", align)
                    }
                }
            }
        };
        UE.commands["cellvalign"] = {
            queryCommandState: function() {
                return getSelectedArr(this).length ? 0 : -1
            },
            execCommand: function(cmd, valign) {
                var selectedTds = getSelectedArr(this);
                if (selectedTds.length) {
                    for (var i = 0, ci; ci = selectedTds[i++];) {
                        ci.setAttribute("vAlign", valign)
                    }
                }
            }
        };
        UE.commands["insertcaption"] = {
            queryCommandState: function() {
                var table = getTableItemsByRange(this).table;
                if (table) {
                    return table.getElementsByTagName("caption").length == 0 ? 1 : -1
                }
                return -1
            },
            execCommand: function() {
                var table = getTableItemsByRange(this).table;
                if (table) {
                    var caption = this.document.createElement("caption");
                    caption.innerHTML = browser.ie ? domUtils.fillChar : "<br/>";
                    table.insertBefore(caption, table.firstChild);
                    var range = this.selection.getRange();
                    range.setStart(caption, 0).setCursor()
                }
            }
        };
        UE.commands["deletecaption"] = {
            queryCommandState: function() {
                var rng = this.selection.getRange(),
                    table = domUtils.findParentByTagName(rng.startContainer, "table");
                if (table) {
                    return table.getElementsByTagName("caption").length == 0 ? -1 : 1
                }
                return -1
            },
            execCommand: function() {
                var rng = this.selection.getRange(),
                    table = domUtils.findParentByTagName(rng.startContainer, "table");
                if (table) {
                    domUtils.remove(table.getElementsByTagName("caption")[0]);
                    var range = this.selection.getRange();
                    range.setStart(table.rows[0].cells[0], 0).setCursor()
                }
            }
        };
        UE.commands["inserttitle"] = {
            queryCommandState: function() {
                var table = getTableItemsByRange(this).table;
                if (table) {
                    var firstRow = table.rows[0];
                    return firstRow.cells[firstRow.cells.length - 1].tagName.toLowerCase() != "th" ? 0 : -1
                }
                return -1
            },
            execCommand: function() {
                var table = getTableItemsByRange(this).table;
                if (table) {
                    getUETable(table).insertRow(0, "th")
                }
                var th = table.getElementsByTagName("th")[0];
                this.selection.getRange().setStart(th, 0).setCursor(false, true)
            }
        };
        UE.commands["deletetitle"] = {
            queryCommandState: function() {
                var table = getTableItemsByRange(this).table;
                if (table) {
                    var firstRow = table.rows[0];
                    return firstRow.cells[firstRow.cells.length - 1].tagName.toLowerCase() == "th" ? 0 : -1
                }
                return -1
            },
            execCommand: function() {
                var table = getTableItemsByRange(this).table;
                if (table) {
                    domUtils.remove(table.rows[0])
                }
                var td = table.getElementsByTagName("td")[0];
                this.selection.getRange().setStart(td, 0).setCursor(false, true)
            }
        };
        UE.commands["inserttitlecol"] = {
            queryCommandState: function() {
                var table = getTableItemsByRange(this).table;
                if (table) {
                    var lastRow = table.rows[table.rows.length - 1];
                    return lastRow.getElementsByTagName("th").length ? -1 : 0
                }
                return -1
            },
            execCommand: function(cmd) {
                var table = getTableItemsByRange(this).table;
                if (table) {
                    getUETable(table).insertCol(0, "th")
                }
                resetTdWidth(table, this);
                var th = table.getElementsByTagName("th")[0];
                this.selection.getRange().setStart(th, 0).setCursor(false, true)
            }
        };
        UE.commands["deletetitlecol"] = {
            queryCommandState: function() {
                var table = getTableItemsByRange(this).table;
                if (table) {
                    var lastRow = table.rows[table.rows.length - 1];
                    return lastRow.getElementsByTagName("th").length ? 0 : -1
                }
                return -1
            },
            execCommand: function() {
                var table = getTableItemsByRange(this).table;
                if (table) {
                    for (var i = 0; i < table.rows.length; i++) {
                        domUtils.remove(table.rows[i].children[0])
                    }
                }
                resetTdWidth(table, this);
                var td = table.getElementsByTagName("td")[0];
                this.selection.getRange().setStart(td, 0).setCursor(false, true)
            }
        };
        UE.commands["mergeright"] = {
            queryCommandState: function(cmd) {
                var tableItems = getTableItemsByRange(this),
                    table = tableItems.table,
                    cell = tableItems.cell;
                if (!table || !cell) {
                    return -1
                }
                var ut = getUETable(table);
                if (ut.selectedTds.length) {
                    return -1
                }
                var cellInfo = ut.getCellInfo(cell),
                    rightColIndex = cellInfo.colIndex + cellInfo.colSpan;
                if (rightColIndex >= ut.colsNum) {
                    return -1
                }
                var rightCellInfo = ut.indexTable[cellInfo.rowIndex][rightColIndex],
                    rightCell = table.rows[rightCellInfo.rowIndex].cells[rightCellInfo.cellIndex];
                if (!rightCell || cell.tagName != rightCell.tagName) {
                    return -1
                }
                return (rightCellInfo.rowIndex == cellInfo.rowIndex && rightCellInfo.rowSpan == cellInfo.rowSpan) ? 0 : -1
            },
            execCommand: function(cmd) {
                var rng = this.selection.getRange(),
                    bk = rng.createBookmark(true);
                var cell = getTableItemsByRange(this).cell,
                    ut = getUETable(cell);
                ut.mergeRight(cell);
                rng.moveToBookmark(bk).select()
            }
        };
        UE.commands["mergedown"] = {
            queryCommandState: function(cmd) {
                var tableItems = getTableItemsByRange(this),
                    table = tableItems.table,
                    cell = tableItems.cell;
                if (!table || !cell) {
                    return -1
                }
                var ut = getUETable(table);
                if (ut.selectedTds.length) {
                    return -1
                }
                var cellInfo = ut.getCellInfo(cell),
                    downRowIndex = cellInfo.rowIndex + cellInfo.rowSpan;
                if (downRowIndex >= ut.rowsNum) {
                    return -1
                }
                var downCellInfo = ut.indexTable[downRowIndex][cellInfo.colIndex],
                    downCell = table.rows[downCellInfo.rowIndex].cells[downCellInfo.cellIndex];
                if (!downCell || cell.tagName != downCell.tagName) {
                    return -1
                }
                return (downCellInfo.colIndex == cellInfo.colIndex && downCellInfo.colSpan == cellInfo.colSpan) ? 0 : -1
            },
            execCommand: function() {
                var rng = this.selection.getRange(),
                    bk = rng.createBookmark(true);
                var cell = getTableItemsByRange(this).cell,
                    ut = getUETable(cell);
                ut.mergeDown(cell);
                rng.moveToBookmark(bk).select()
            }
        };
        UE.commands["mergecells"] = {
            queryCommandState: function() {
                return getUETableBySelected(this) ? 0 : -1
            },
            execCommand: function() {
                var ut = getUETableBySelected(this);
                if (ut && ut.selectedTds.length) {
                    var cell = ut.selectedTds[0];
                    ut.mergeRange();
                    var rng = this.selection.getRange();
                    if (domUtils.isEmptyBlock(cell)) {
                        rng.setStart(cell, 0).collapse(true)
                    } else {
                        rng.selectNodeContents(cell)
                    }
                    rng.select()
                }
            }
        };
        UE.commands["insertrow"] = {
            queryCommandState: function() {
                var tableItems = getTableItemsByRange(this),
                    cell = tableItems.cell;
                return cell && (cell.tagName == "TD" || (cell.tagName == "TH" && tableItems.tr !== tableItems.table.rows[0])) && getUETable(tableItems.table).rowsNum < this.options.maxRowNum ? 0 : -1
            },
            execCommand: function() {
                var rng = this.selection.getRange(),
                    bk = rng.createBookmark(true);
                var tableItems = getTableItemsByRange(this),
                    cell = tableItems.cell,
                    table = tableItems.table,
                    ut = getUETable(table),
                    cellInfo = ut.getCellInfo(cell);
                if (!ut.selectedTds.length) {
                    ut.insertRow(cellInfo.rowIndex, cell)
                } else {
                    var range = ut.cellsRange;
                    for (var i = 0, len = range.endRowIndex - range.beginRowIndex + 1; i < len; i++) {
                        ut.insertRow(range.beginRowIndex, cell)
                    }
                }
                rng.moveToBookmark(bk).select();
                if (table.getAttribute("interlaced") === "enabled") {
                    this.fireEvent("interlacetable", table)
                }
            }
        };
        UE.commands["insertrownext"] = {
            queryCommandState: function() {
                var tableItems = getTableItemsByRange(this),
                    cell = tableItems.cell;
                return cell && (cell.tagName == "TD") && getUETable(tableItems.table).rowsNum < this.options.maxRowNum ? 0 : -1
            },
            execCommand: function() {
                var rng = this.selection.getRange(),
                    bk = rng.createBookmark(true);
                var tableItems = getTableItemsByRange(this),
                    cell = tableItems.cell,
                    table = tableItems.table,
                    ut = getUETable(table),
                    cellInfo = ut.getCellInfo(cell);
                if (!ut.selectedTds.length) {
                    ut.insertRow(cellInfo.rowIndex + cellInfo.rowSpan, cell)
                } else {
                    var range = ut.cellsRange;
                    for (var i = 0, len = range.endRowIndex - range.beginRowIndex + 1; i < len; i++) {
                        ut.insertRow(range.endRowIndex + 1, cell)
                    }
                }
                rng.moveToBookmark(bk).select();
                if (table.getAttribute("interlaced") === "enabled") {
                    this.fireEvent("interlacetable", table)
                }
            }
        };
        UE.commands["deleterow"] = {
            queryCommandState: function() {
                var tableItems = getTableItemsByRange(this);
                return tableItems.cell ? 0 : -1
            },
            execCommand: function() {
                var cell = getTableItemsByRange(this).cell,
                    ut = getUETable(cell),
                    cellsRange = ut.cellsRange,
                    cellInfo = ut.getCellInfo(cell),
                    preCell = ut.getVSideCell(cell),
                    nextCell = ut.getVSideCell(cell, true),
                    rng = this.selection.getRange();
                if (utils.isEmptyObject(cellsRange)) {
                    ut.deleteRow(cellInfo.rowIndex)
                } else {
                    for (var i = cellsRange.beginRowIndex; i < cellsRange.endRowIndex + 1; i++) {
                        ut.deleteRow(cellsRange.beginRowIndex)
                    }
                }
                var table = ut.table;
                if (!table.getElementsByTagName("td").length) {
                    var nextSibling = table.nextSibling;
                    domUtils.remove(table);
                    if (nextSibling) {
                        rng.setStart(nextSibling, 0).setCursor(false, true)
                    }
                } else {
                    if (cellInfo.rowSpan == 1 || cellInfo.rowSpan == cellsRange.endRowIndex - cellsRange.beginRowIndex + 1) {
                        if (nextCell || preCell) {
                            rng.selectNodeContents(nextCell || preCell).setCursor(false, true)
                        }
                    } else {
                        var newCell = ut.getCell(cellInfo.rowIndex, ut.indexTable[cellInfo.rowIndex][cellInfo.colIndex].cellIndex);
                        if (newCell) {
                            rng.selectNodeContents(newCell).setCursor(false, true)
                        }
                    }
                }
                if (table.getAttribute("interlaced") === "enabled") {
                    this.fireEvent("interlacetable", table)
                }
            }
        };
        UE.commands["insertcol"] = {
            queryCommandState: function(cmd) {
                var tableItems = getTableItemsByRange(this),
                    cell = tableItems.cell;
                return cell && (cell.tagName == "TD" || (cell.tagName == "TH" && cell !== tableItems.tr.cells[0])) && getUETable(tableItems.table).colsNum < this.options.maxColNum ? 0 : -1
            },
            execCommand: function(cmd) {
                var rng = this.selection.getRange(),
                    bk = rng.createBookmark(true);
                if (this.queryCommandState(cmd) == -1) {
                    return
                }
                var cell = getTableItemsByRange(this).cell,
                    ut = getUETable(cell),
                    cellInfo = ut.getCellInfo(cell);
                if (!ut.selectedTds.length) {
                    ut.insertCol(cellInfo.colIndex, cell)
                } else {
                    var range = ut.cellsRange;
                    for (var i = 0, len = range.endColIndex - range.beginColIndex + 1; i < len; i++) {
                        ut.insertCol(range.beginColIndex, cell)
                    }
                }
                rng.moveToBookmark(bk).select(true)
            }
        };
        UE.commands["insertcolnext"] = {
            queryCommandState: function() {
                var tableItems = getTableItemsByRange(this),
                    cell = tableItems.cell;
                return cell && getUETable(tableItems.table).colsNum < this.options.maxColNum ? 0 : -1
            },
            execCommand: function() {
                var rng = this.selection.getRange(),
                    bk = rng.createBookmark(true);
                var cell = getTableItemsByRange(this).cell,
                    ut = getUETable(cell),
                    cellInfo = ut.getCellInfo(cell);
                if (!ut.selectedTds.length) {
                    ut.insertCol(cellInfo.colIndex + cellInfo.colSpan, cell)
                } else {
                    var range = ut.cellsRange;
                    for (var i = 0, len = range.endColIndex - range.beginColIndex + 1; i < len; i++) {
                        ut.insertCol(range.endColIndex + 1, cell)
                    }
                }
                rng.moveToBookmark(bk).select()
            }
        };
        UE.commands["deletecol"] = {
            queryCommandState: function() {
                var tableItems = getTableItemsByRange(this);
                return tableItems.cell ? 0 : -1
            },
            execCommand: function() {
                var cell = getTableItemsByRange(this).cell,
                    ut = getUETable(cell),
                    range = ut.cellsRange,
                    cellInfo = ut.getCellInfo(cell),
                    preCell = ut.getHSideCell(cell),
                    nextCell = ut.getHSideCell(cell, true);
                if (utils.isEmptyObject(range)) {
                    ut.deleteCol(cellInfo.colIndex)
                } else {
                    for (var i = range.beginColIndex; i < range.endColIndex + 1; i++) {
                        ut.deleteCol(range.beginColIndex)
                    }
                }
                var table = ut.table,
                    rng = this.selection.getRange();
                if (!table.getElementsByTagName("td").length) {
                    var nextSibling = table.nextSibling;
                    domUtils.remove(table);
                    if (nextSibling) {
                        rng.setStart(nextSibling, 0).setCursor(false, true)
                    }
                } else {
                    if (domUtils.inDoc(cell, this.document)) {
                        rng.setStart(cell, 0).setCursor(false, true)
                    } else {
                        if (nextCell && domUtils.inDoc(nextCell, this.document)) {
                            rng.selectNodeContents(nextCell).setCursor(false, true)
                        } else {
                            if (preCell && domUtils.inDoc(preCell, this.document)) {
                                rng.selectNodeContents(preCell).setCursor(true, true)
                            }
                        }
                    }
                }
            }
        };
        UE.commands["splittocells"] = {
            queryCommandState: function() {
                var tableItems = getTableItemsByRange(this),
                    cell = tableItems.cell;
                if (!cell) {
                    return -1
                }
                var ut = getUETable(tableItems.table);
                if (ut.selectedTds.length > 0) {
                    return -1
                }
                return cell && (cell.colSpan > 1 || cell.rowSpan > 1) ? 0 : -1
            },
            execCommand: function() {
                var rng = this.selection.getRange(),
                    bk = rng.createBookmark(true);
                var cell = getTableItemsByRange(this).cell,
                    ut = getUETable(cell);
                ut.splitToCells(cell);
                rng.moveToBookmark(bk).select()
            }
        };
        UE.commands["splittorows"] = {
            queryCommandState: function() {
                var tableItems = getTableItemsByRange(this),
                    cell = tableItems.cell;
                if (!cell) {
                    return -1
                }
                var ut = getUETable(tableItems.table);
                if (ut.selectedTds.length > 0) {
                    return -1
                }
                return cell && cell.rowSpan > 1 ? 0 : -1
            },
            execCommand: function() {
                var rng = this.selection.getRange(),
                    bk = rng.createBookmark(true);
                var cell = getTableItemsByRange(this).cell,
                    ut = getUETable(cell);
                ut.splitToRows(cell);
                rng.moveToBookmark(bk).select()
            }
        };
        UE.commands["splittocols"] = {
            queryCommandState: function() {
                var tableItems = getTableItemsByRange(this),
                    cell = tableItems.cell;
                if (!cell) {
                    return -1
                }
                var ut = getUETable(tableItems.table);
                if (ut.selectedTds.length > 0) {
                    return -1
                }
                return cell && cell.colSpan > 1 ? 0 : -1
            },
            execCommand: function() {
                var rng = this.selection.getRange(),
                    bk = rng.createBookmark(true);
                var cell = getTableItemsByRange(this).cell,
                    ut = getUETable(cell);
                ut.splitToCols(cell);
                rng.moveToBookmark(bk).select()
            }
        };
        UE.commands["adaptbytext"] = UE.commands["adaptbywindow"] = {
            queryCommandState: function() {
                return getTableItemsByRange(this).table ? 0 : -1
            },
            execCommand: function(cmd) {
                var tableItems = getTableItemsByRange(this),
                    table = tableItems.table;
                if (table) {
                    if (cmd == "adaptbywindow") {
                        resetTdWidth(table, this)
                    } else {
                        var cells = domUtils.getElementsByTagName(table, "td th");
                        utils.each(cells, function(cell) {
                            cell.removeAttribute("width")
                        });
                        table.removeAttribute("width")
                    }
                }
            }
        };
        UE.commands["averagedistributecol"] = {
            queryCommandState: function() {
                var ut = getUETableBySelected(this);
                if (!ut) {
                    return -1
                }
                return ut.isFullRow() || ut.isFullCol() ? 0 : -1
            },
            execCommand: function(cmd) {
                var me = this,
                    ut = getUETableBySelected(me);

                function getAverageWidth() {
                    var tb = ut.table,
                        averageWidth, sumWidth = 0,
                        colsNum = 0,
                        tbAttr = getDefaultValue(me, tb);
                    if (ut.isFullRow()) {
                        sumWidth = tb.offsetWidth;
                        colsNum = ut.colsNum
                    } else {
                        var begin = ut.cellsRange.beginColIndex,
                            end = ut.cellsRange.endColIndex,
                            node;
                        for (var i = begin; i <= end;) {
                            node = ut.selectedTds[i];
                            sumWidth += node.offsetWidth;
                            i += node.colSpan;
                            colsNum += 1
                        }
                    }
                    averageWidth = Math.ceil(sumWidth / colsNum) - tbAttr.tdBorder * 2 - tbAttr.tdPadding * 2;
                    return averageWidth
                }
                function setAverageWidth(averageWidth) {
                    utils.each(domUtils.getElementsByTagName(ut.table, "th"), function(node) {
                        node.setAttribute("width", "")
                    });
                    var cells = ut.isFullRow() ? domUtils.getElementsByTagName(ut.table, "td") : ut.selectedTds;
                    utils.each(cells, function(node) {
                        if (node.colSpan == 1) {
                            node.setAttribute("width", averageWidth)
                        }
                    })
                }
                if (ut && ut.selectedTds.length) {
                    setAverageWidth(getAverageWidth())
                }
            }
        };
        UE.commands["averagedistributerow"] = {
            queryCommandState: function() {
                var ut = getUETableBySelected(this);
                if (!ut) {
                    return -1
                }
                if (ut.selectedTds && /th/ig.test(ut.selectedTds[0].tagName)) {
                    return -1
                }
                return ut.isFullRow() || ut.isFullCol() ? 0 : -1
            },
            execCommand: function(cmd) {
                var me = this,
                    ut = getUETableBySelected(me);

                function getAverageHeight() {
                    var averageHeight, rowNum, sumHeight = 0,
                        tb = ut.table,
                        tbAttr = getDefaultValue(me, tb),
                        tdpadding = parseInt(domUtils.getComputedStyle(tb.getElementsByTagName("td")[0], "padding-top"));
                    if (ut.isFullCol()) {
                        var captionArr = domUtils.getElementsByTagName(tb, "caption"),
                            thArr = domUtils.getElementsByTagName(tb, "th"),
                            captionHeight, thHeight;
                        if (captionArr.length > 0) {
                            captionHeight = captionArr[0].offsetHeight
                        }
                        if (thArr.length > 0) {
                            thHeight = thArr[0].offsetHeight
                        }
                        sumHeight = tb.offsetHeight - (captionHeight || 0) - (thHeight || 0);
                        rowNum = thArr.length == 0 ? ut.rowsNum : (ut.rowsNum - 1)
                    } else {
                        var begin = ut.cellsRange.beginRowIndex,
                            end = ut.cellsRange.endRowIndex,
                            count = 0,
                            trs = domUtils.getElementsByTagName(tb, "tr");
                        for (var i = begin; i <= end; i++) {
                            sumHeight += trs[i].offsetHeight;
                            count += 1
                        }
                        rowNum = count
                    }
                    if (browser.ie && browser.version < 9) {
                        averageHeight = Math.ceil(sumHeight / rowNum)
                    } else {
                        averageHeight = Math.ceil(sumHeight / rowNum) - tbAttr.tdBorder * 2 - tdpadding * 2
                    }
                    return averageHeight
                }
                function setAverageHeight(averageHeight) {
                    var cells = ut.isFullCol() ? domUtils.getElementsByTagName(ut.table, "td") : ut.selectedTds;
                    utils.each(cells, function(node) {
                        if (node.rowSpan == 1) {
                            node.setAttribute("height", averageHeight)
                        }
                    })
                }
                if (ut && ut.selectedTds.length) {
                    setAverageHeight(getAverageHeight())
                }
            }
        };
        UE.commands["cellalignment"] = {
            queryCommandState: function() {
                return getTableItemsByRange(this).table ? 0 : -1
            },
            execCommand: function(cmd, data) {
                var me = this,
                    ut = getUETableBySelected(me);
                if (!ut) {
                    var start = me.selection.getStart(),
                        cell = start && domUtils.findParentByTagName(start, ["td", "th", "caption"], true);
                    if (!/caption/ig.test(cell.tagName)) {
                        domUtils.setAttributes(cell, data)
                    } else {
                        cell.style.textAlign = data.align;
                        cell.style.verticalAlign = data.vAlign
                    }
                    me.selection.getRange().setCursor(true)
                } else {
                    utils.each(ut.selectedTds, function(cell) {
                        domUtils.setAttributes(cell, data)
                    })
                }
            },
            queryCommandValue: function(cmd) {
                var activeMenuCell = getTableItemsByRange(this).cell;
                if (!activeMenuCell) {
                    activeMenuCell = getSelectedArr(this)[0]
                }
                if (!activeMenuCell) {
                    return null
                } else {
                    var cells = UE.UETable.getUETable(activeMenuCell).selectedTds;
                    !cells.length && (cells = activeMenuCell);
                    return UE.UETable.getTableCellAlignState(cells)
                }
            }
        };
        UE.commands["tablealignment"] = {
            queryCommandState: function() {
                if (browser.ie && browser.version < 8) {
                    return -1
                }
                return getTableItemsByRange(this).table ? 0 : -1
            },
            execCommand: function(cmd, value) {
                var me = this,
                    start = me.selection.getStart(),
                    table = start && domUtils.findParentByTagName(start, ["table"], true);
                if (table) {
                    table.setAttribute("align", value)
                }
            }
        };
        UE.commands["edittable"] = {
            queryCommandState: function() {
                return getTableItemsByRange(this).table ? 0 : -1
            },
            execCommand: function(cmd, color) {
                var rng = this.selection.getRange(),
                    table = domUtils.findParentByTagName(rng.startContainer, "table");
                if (table) {
                    var arr = domUtils.getElementsByTagName(table, "td").concat(domUtils.getElementsByTagName(table, "th"), domUtils.getElementsByTagName(table, "caption"));
                    utils.each(arr, function(node) {
                        node.style.borderColor = color
                    })
                }
            }
        };
        UE.commands["edittd"] = {
            queryCommandState: function() {
                return getTableItemsByRange(this).table ? 0 : -1
            },
            execCommand: function(cmd, bkColor) {
                var me = this,
                    ut = getUETableBySelected(me);
                if (!ut) {
                    var start = me.selection.getStart(),
                        cell = start && domUtils.findParentByTagName(start, ["td", "th", "caption"], true);
                    if (cell) {
                        cell.style.backgroundColor = bkColor
                    }
                } else {
                    utils.each(ut.selectedTds, function(cell) {
                        cell.style.backgroundColor = bkColor
                    })
                }
            }
        };
        UE.commands["settablebackground"] = {
            queryCommandState: function() {
                return getSelectedArr(this).length > 1 ? 0 : -1
            },
            execCommand: function(cmd, value) {
                var cells, ut;
                cells = getSelectedArr(this);
                ut = getUETable(cells[0]);
                ut.setBackground(cells, value)
            }
        };
        UE.commands["cleartablebackground"] = {
            queryCommandState: function() {
                var cells = getSelectedArr(this);
                if (!cells.length) {
                    return -1
                }
                for (var i = 0, cell; cell = cells[i++];) {
                    if (cell.style.backgroundColor !== "") {
                        return 0
                    }
                }
                return -1
            },
            execCommand: function() {
                var cells = getSelectedArr(this),
                    ut = getUETable(cells[0]);
                ut.removeBackground(cells)
            }
        };
        UE.commands["interlacetable"] = UE.commands["uninterlacetable"] = {
            queryCommandState: function(cmd) {
                var table = getTableItemsByRange(this).table;
                if (!table) {
                    return -1
                }
                var interlaced = table.getAttribute("interlaced");
                if (cmd == "interlacetable") {
                    return (interlaced === "enabled") ? -1 : 0
                } else {
                    return (!interlaced || interlaced === "disabled") ? -1 : 0
                }
            },
            execCommand: function(cmd, classList) {
                var table = getTableItemsByRange(this).table;
                if (cmd == "interlacetable") {
                    table.setAttribute("interlaced", "enabled");
                    this.fireEvent("interlacetable", table, classList)
                } else {
                    table.setAttribute("interlaced", "disabled");
                    this.fireEvent("uninterlacetable", table)
                }
            }
        };
        UE.commands["setbordervisible"] = {
            queryCommandState: function(cmd) {
                var table = getTableItemsByRange(this).table;
                if (!table) {
                    return -1
                }
                return 0
            },
            execCommand: function() {
                var table = getTableItemsByRange(this).table;
                utils.each(domUtils.getElementsByTagName(table, "td"), function(td) {
                    td.style.borderWidth = "1px";
                    td.style.borderStyle = "solid"
                })
            }
        };

        function resetTdWidth(table, editor) {
            var tds = domUtils.getElementsByTagName(table, "td th");
            utils.each(tds, function(td) {
                td.removeAttribute("width")
            });
            table.setAttribute("width", getTableWidth(editor, true, getDefaultValue(editor, table)));
            var tdsWidths = [];
            setTimeout(function() {
                utils.each(tds, function(td) {
                    (td.colSpan == 1) && tdsWidths.push(td.offsetWidth)
                });
                utils.each(tds, function(td, i) {
                    (td.colSpan == 1) && td.setAttribute("width", tdsWidths[i] + "")
                })
            }, 0)
        }
        function getTableWidth(editor, needIEHack, defaultValue) {
            var body = editor.body;
            return body.offsetWidth - (needIEHack ? parseInt(domUtils.getComputedStyle(body, "margin-left"), 10) * 2 : 0) - defaultValue.tableBorder * 2 - (editor.options.offsetWidth || 0)
        }
        function getSelectedArr(editor) {
            var cell = getTableItemsByRange(editor).cell;
            if (cell) {
                var ut = getUETable(cell);
                return ut.selectedTds.length ? ut.selectedTds : [cell]
            } else {
                return []
            }
        }
    })();
    UE.plugins["table"] = function() {
        var me = this,
            tabTimer = null,
            tableDragTimer = null,
            tableResizeTimer = null,
            cellMinWidth = 5,
            isInResizeBuffer = false,
            cellBorderWidth = 5,
            offsetOfTableCell = 10,
            singleClickState = 0,
            userActionStatus = null,
            dblclickTime = 360,
            UT = UE.UETable,
            getUETable = function(tdOrTable) {
                return UT.getUETable(tdOrTable)
            },
            getUETableBySelected = function(editor) {
                return UT.getUETableBySelected(editor)
            },
            getDefaultValue = function(editor, table) {
                return UT.getDefaultValue(editor, table)
            },
            removeSelectedClass = function(cells) {
                return UT.removeSelectedClass(cells)
            };

        function showError(e) {}
        me.ready(function() {
            var me = this;
            var orgGetText = me.selection.getText;
            me.selection.getText = function() {
                var table = getUETableBySelected(me);
                if (table) {
                    var str = "";
                    utils.each(table.selectedTds, function(td) {
                        str += td[browser.ie ? "innerText" : "textContent"]
                    });
                    return str
                } else {
                    return orgGetText.call(me.selection)
                }
            }
        });
        var startTd = null,
            currentTd = null,
            onDrag = "",
            onBorder = false,
            dragButton = null,
            dragOver = false,
            dragLine = null,
            dragTd = null;
        var mousedown = false,
            needIEHack = true;
        me.setOpt({
            "maxColNum": 20,
            "maxRowNum": 100,
            "defaultCols": 5,
            "defaultRows": 5,
            "tdvalign": "top",
            "cursorpath": me.options.UEDITOR_HOME_URL + "themes/default/images/cursor_",
            "tableDragable": false,
            "classList": ["ue-table-interlace-color-single", "ue-table-interlace-color-double"]
        });
        me.getUETable = getUETable;
        var commands = {
            "deletetable": 1,
            "inserttable": 1,
            "cellvalign": 1,
            "insertcaption": 1,
            "deletecaption": 1,
            "inserttitle": 1,
            "deletetitle": 1,
            "mergeright": 1,
            "mergedown": 1,
            "mergecells": 1,
            "insertrow": 1,
            "insertrownext": 1,
            "deleterow": 1,
            "insertcol": 1,
            "insertcolnext": 1,
            "deletecol": 1,
            "splittocells": 1,
            "splittorows": 1,
            "splittocols": 1,
            "adaptbytext": 1,
            "adaptbywindow": 1,
            "adaptbycustomer": 1,
            "insertparagraph": 1,
            "insertparagraphbeforetable": 1,
            "averagedistributecol": 1,
            "averagedistributerow": 1
        };
        me.ready(function() {
            utils.cssRule("table", ".selectTdClass{background-color:#edf5fa !important}" + "table.noBorderTable td,table.noBorderTable th,table.noBorderTable caption{border:1px dashed #ddd !important}" + "table{margin-bottom:10px;border-collapse:collapse;display:table;}" + "td,th{padding: 5px 10px;border: 1px solid #DDD;}" + "caption{border:1px dashed #DDD;border-bottom:0;padding:3px;text-align:center;}" + "th{border-top:1px solid #BBB;background-color:#F7F7F7;}" + "table tr.firstRow th{border-top-width:2px;}" + ".ue-table-interlace-color-single{ background-color: #fcfcfc; } .ue-table-interlace-color-double{ background-color: #f7faff; }" + "td p{margin:0;padding:0;}", me.document);
            var tableCopyList, isFullCol, isFullRow;
            me.addListener("keydown", function(cmd, evt) {
                var me = this;
                var keyCode = evt.keyCode || evt.which;
                if (keyCode == 8) {
                    var ut = getUETableBySelected(me);
                    if (ut && ut.selectedTds.length) {
                        if (ut.isFullCol()) {
                            me.execCommand("deletecol")
                        } else {
                            if (ut.isFullRow()) {
                                me.execCommand("deleterow")
                            } else {
                                me.fireEvent("delcells")
                            }
                        }
                        domUtils.preventDefault(evt)
                    }
                    var caption = domUtils.findParentByTagName(me.selection.getStart(), "caption", true),
                        range = me.selection.getRange();
                    if (range.collapsed && caption && isEmptyBlock(caption)) {
                        me.fireEvent("saveScene");
                        var table = caption.parentNode;
                        domUtils.remove(caption);
                        if (table) {
                            range.setStart(table.rows[0].cells[0], 0).setCursor(false, true)
                        }
                        me.fireEvent("saveScene")
                    }
                }
                if (keyCode == 46) {
                    ut = getUETableBySelected(me);
                    if (ut) {
                        me.fireEvent("saveScene");
                        for (var i = 0, ci; ci = ut.selectedTds[i++];) {
                            domUtils.fillNode(me.document, ci)
                        }
                        me.fireEvent("saveScene");
                        domUtils.preventDefault(evt)
                    }
                }
                if (keyCode == 13) {
                    var rng = me.selection.getRange(),
                        caption = domUtils.findParentByTagName(rng.startContainer, "caption", true);
                    if (caption) {
                        var table = domUtils.findParentByTagName(caption, "table");
                        if (!rng.collapsed) {
                            rng.deleteContents();
                            me.fireEvent("saveScene")
                        } else {
                            if (caption) {
                                rng.setStart(table.rows[0].cells[0], 0).setCursor(false, true)
                            }
                        }
                        domUtils.preventDefault(evt);
                        return
                    }
                    if (rng.collapsed) {
                        var table = domUtils.findParentByTagName(rng.startContainer, "table");
                        if (table) {
                            var cell = table.rows[0].cells[0],
                                start = domUtils.findParentByTagName(me.selection.getStart(), ["td", "th"], true),
                                preNode = table.previousSibling;
                            if (cell === start && (!preNode || preNode.nodeType == 1 && preNode.tagName == "TABLE") && domUtils.isStartInblock(rng)) {
                                var first = domUtils.findParent(me.selection.getStart(), function(n) {
                                    return domUtils.isBlockElm(n)
                                }, true);
                                if (first && (/t(h|d)/i.test(first.tagName) || first === start.firstChild)) {
                                    me.execCommand("insertparagraphbeforetable");
                                    domUtils.preventDefault(evt)
                                }
                            }
                        }
                    }
                }
                if ((evt.ctrlKey || evt.metaKey) && evt.keyCode == "67") {
                    tableCopyList = null;
                    var ut = getUETableBySelected(me);
                    if (ut) {
                        var tds = ut.selectedTds;
                        isFullCol = ut.isFullCol();
                        isFullRow = ut.isFullRow();
                        tableCopyList = [
                            [ut.cloneCell(tds[0], null, true)]
                        ];
                        for (var i = 1, ci; ci = tds[i]; i++) {
                            if (ci.parentNode !== tds[i - 1].parentNode) {
                                tableCopyList.push([ut.cloneCell(ci, null, true)])
                            } else {
                                tableCopyList[tableCopyList.length - 1].push(ut.cloneCell(ci, null, true))
                            }
                        }
                    }
                }
            });
            me.addListener("tablehasdeleted", function() {
                toggleDraggableState(this, false, "", null);
                if (dragButton) {
                    domUtils.remove(dragButton)
                }
            });
            me.addListener("beforepaste", function(cmd, html) {
                var me = this;
                var rng = me.selection.getRange();
                if (domUtils.findParentByTagName(rng.startContainer, "caption", true)) {
                    var div = me.document.createElement("div");
                    div.innerHTML = html.html;
                    html.html = div[browser.ie9below ? "innerText" : "textContent"];
                    return
                }
                var table = getUETableBySelected(me);
                if (tableCopyList) {
                    me.fireEvent("saveScene");
                    var rng = me.selection.getRange();
                    var td = domUtils.findParentByTagName(rng.startContainer, ["td", "th"], true),
                        tmpNode, preNode;
                    if (td) {
                        var ut = getUETable(td);
                        if (isFullRow) {
                            var rowIndex = ut.getCellInfo(td).rowIndex;
                            if (td.tagName == "TH") {
                                rowIndex++
                            }
                            for (var i = 0, ci; ci = tableCopyList[i++];) {
                                var tr = ut.insertRow(rowIndex++, "td");
                                for (var j = 0, cj; cj = ci[j]; j++) {
                                    var cell = tr.cells[j];
                                    if (!cell) {
                                        cell = tr.insertCell(j)
                                    }
                                    cell.innerHTML = cj.innerHTML;
                                    cj.getAttribute("width") && cell.setAttribute("width", cj.getAttribute("width"));
                                    cj.getAttribute("vAlign") && cell.setAttribute("vAlign", cj.getAttribute("vAlign"));
                                    cj.getAttribute("align") && cell.setAttribute("align", cj.getAttribute("align"));
                                    cj.style.cssText && (cell.style.cssText = cj.style.cssText)
                                }
                                for (var j = 0, cj; cj = tr.cells[j]; j++) {
                                    if (!ci[j]) {
                                        break
                                    }
                                    cj.innerHTML = ci[j].innerHTML;
                                    ci[j].getAttribute("width") && cj.setAttribute("width", ci[j].getAttribute("width"));
                                    ci[j].getAttribute("vAlign") && cj.setAttribute("vAlign", ci[j].getAttribute("vAlign"));
                                    ci[j].getAttribute("align") && cj.setAttribute("align", ci[j].getAttribute("align"));
                                    ci[j].style.cssText && (cj.style.cssText = ci[j].style.cssText)
                                }
                            }
                        } else {
                            if (isFullCol) {
                                cellInfo = ut.getCellInfo(td);
                                var maxColNum = 0;
                                for (var j = 0, ci = tableCopyList[0], cj; cj = ci[j++];) {
                                    maxColNum += cj.colSpan || 1
                                }
                                me.__hasEnterExecCommand = true;
                                for (i = 0; i < maxColNum; i++) {
                                    me.execCommand("insertcol")
                                }
                                me.__hasEnterExecCommand = false;
                                td = ut.table.rows[0].cells[cellInfo.cellIndex];
                                if (td.tagName == "TH") {
                                    td = ut.table.rows[1].cells[cellInfo.cellIndex]
                                }
                            }
                            for (var i = 0, ci; ci = tableCopyList[i++];) {
                                tmpNode = td;
                                for (var j = 0, cj; cj = ci[j++];) {
                                    if (td) {
                                        td.innerHTML = cj.innerHTML;
                                        cj.getAttribute("width") && td.setAttribute("width", cj.getAttribute("width"));
                                        cj.getAttribute("vAlign") && td.setAttribute("vAlign", cj.getAttribute("vAlign"));
                                        cj.getAttribute("align") && td.setAttribute("align", cj.getAttribute("align"));
                                        cj.style.cssText && (td.style.cssText = cj.style.cssText);
                                        preNode = td;
                                        td = td.nextSibling
                                    } else {
                                        var cloneTd = cj.cloneNode(true);
                                        domUtils.removeAttributes(cloneTd, ["class", "rowSpan", "colSpan"]);
                                        preNode.parentNode.appendChild(cloneTd)
                                    }
                                }
                                td = ut.getNextCell(tmpNode, true, true);
                                if (!tableCopyList[i]) {
                                    break
                                }
                                if (!td) {
                                    var cellInfo = ut.getCellInfo(tmpNode);
                                    ut.table.insertRow(ut.table.rows.length);
                                    ut.update();
                                    td = ut.getVSideCell(tmpNode, true)
                                }
                            }
                        }
                        ut.update()
                    } else {
                        table = me.document.createElement("table");
                        for (var i = 0, ci; ci = tableCopyList[i++];) {
                            var tr = table.insertRow(table.rows.length);
                            for (var j = 0, cj; cj = ci[j++];) {
                                cloneTd = UT.cloneCell(cj, null, true);
                                domUtils.removeAttributes(cloneTd, ["class"]);
                                tr.appendChild(cloneTd)
                            }
                            if (j == 2 && cloneTd.rowSpan > 1) {
                                cloneTd.rowSpan = 1
                            }
                        }
                        var defaultValue = getDefaultValue(me),
                            width = me.body.offsetWidth - (needIEHack ? parseInt(domUtils.getComputedStyle(me.body, "margin-left"), 10) * 2 : 0) - defaultValue.tableBorder * 2 - (me.options.offsetWidth || 0);
                        me.execCommand("insertHTML", "<table  " + (isFullCol && isFullRow ? 'width="' + width + '"' : "") + ">" + table.innerHTML.replace(/>\s*</g, "><").replace(/\bth\b/gi, "td") + "</table>")
                    }
                    me.fireEvent("contentchange");
                    me.fireEvent("saveScene");
                    html.html = "";
                    return true
                } else {
                    var div = me.document.createElement("div"),
                        tables;
                    div.innerHTML = html.html;
                    tables = div.getElementsByTagName("table");
                    if (domUtils.findParentByTagName(me.selection.getStart(), "table")) {
                        utils.each(tables, function(t) {
                            domUtils.remove(t)
                        });
                        if (domUtils.findParentByTagName(me.selection.getStart(), "caption", true)) {
                            div.innerHTML = div[browser.ie ? "innerText" : "textContent"]
                        }
                    } else {
                        utils.each(tables, function(table) {
                            removeStyleSize(table, true);
                            domUtils.removeAttributes(table, ["style", "border"]);
                            utils.each(domUtils.getElementsByTagName(table, "td"), function(td) {
                                if (isEmptyBlock(td)) {
                                    domUtils.fillNode(me.document, td)
                                }
                                removeStyleSize(td, true)
                            })
                        })
                    }
                    html.html = div.innerHTML
                }
            });
            me.addListener("afterpaste", function() {
                utils.each(domUtils.getElementsByTagName(me.body, "table"), function(table) {
                    if (table.offsetWidth > me.body.offsetWidth) {
                        var defaultValue = getDefaultValue(me, table);
                        table.style.width = me.body.offsetWidth - (needIEHack ? parseInt(domUtils.getComputedStyle(me.body, "margin-left"), 10) * 2 : 0) - defaultValue.tableBorder * 2 - (me.options.offsetWidth || 0) + "px"
                    }
                })
            });
            me.addListener("blur", function() {
                tableCopyList = null
            });
            var timer;
            me.addListener("keydown", function() {
                clearTimeout(timer);
                timer = setTimeout(function() {
                    var rng = me.selection.getRange(),
                        cell = domUtils.findParentByTagName(rng.startContainer, ["th", "td"], true);
                    if (cell) {
                        var table = cell.parentNode.parentNode.parentNode;
                        if (table.offsetWidth > table.getAttribute("width")) {
                            cell.style.wordBreak = "break-all"
                        }
                    }
                }, 100)
            });
            me.addListener("selectionchange", function() {
                toggleDraggableState(me, false, "", null)
            });
            me.addListener("contentchange", function() {
                var me = this;
                hideDragLine(me);
                if (getUETableBySelected(me)) {
                    return
                }
                var rng = me.selection.getRange();
                var start = rng.startContainer;
                start = domUtils.findParentByTagName(start, ["td", "th"], true);
                utils.each(domUtils.getElementsByTagName(me.document, "table"), function(table) {
                    if (me.fireEvent("excludetable", table) === true) {
                        return
                    }
                    table.ueTable = new UT(table);
                    table.onmouseover = function() {
                        me.fireEvent("tablemouseover", table)
                    };
                    table.onmousemove = function() {
                        me.fireEvent("tablemousemove", table);
                        me.options.tableDragable && toggleDragButton(true, this, me);
                        utils.defer(function() {
                            me.fireEvent("contentchange", 50)
                        }, true)
                    };
                    table.onmouseout = function() {
                        me.fireEvent("tablemouseout", table);
                        toggleDraggableState(me, false, "", null);
                        hideDragLine(me)
                    };
                    table.onclick = function(evt) {
                        evt = me.window.event || evt;
                        var target = getParentTdOrTh(evt.target || evt.srcElement);
                        if (!target) {
                            return
                        }
                        var ut = getUETable(target),
                            table = ut.table,
                            cellInfo = ut.getCellInfo(target),
                            cellsRange, rng = me.selection.getRange();
                        if (inTableSide(table, target, evt, true)) {
                            var endTdCol = ut.getCell(ut.indexTable[ut.rowsNum - 1][cellInfo.colIndex].rowIndex, ut.indexTable[ut.rowsNum - 1][cellInfo.colIndex].cellIndex);
                            if (evt.shiftKey && ut.selectedTds.length) {
                                if (ut.selectedTds[0] !== endTdCol) {
                                    cellsRange = ut.getCellsRange(ut.selectedTds[0], endTdCol);
                                    ut.setSelected(cellsRange)
                                } else {
                                    rng && rng.selectNodeContents(endTdCol).select()
                                }
                            } else {
                                if (target !== endTdCol) {
                                    cellsRange = ut.getCellsRange(target, endTdCol);
                                    ut.setSelected(cellsRange)
                                } else {
                                    rng && rng.selectNodeContents(endTdCol).select()
                                }
                            }
                            return
                        }
                        if (inTableSide(table, target, evt)) {
                            var endTdRow = ut.getCell(ut.indexTable[cellInfo.rowIndex][ut.colsNum - 1].rowIndex, ut.indexTable[cellInfo.rowIndex][ut.colsNum - 1].cellIndex);
                            if (evt.shiftKey && ut.selectedTds.length) {
                                if (ut.selectedTds[0] !== endTdRow) {
                                    cellsRange = ut.getCellsRange(ut.selectedTds[0], endTdRow);
                                    ut.setSelected(cellsRange)
                                } else {
                                    rng && rng.selectNodeContents(endTdRow).select()
                                }
                            } else {
                                if (target !== endTdRow) {
                                    cellsRange = ut.getCellsRange(target, endTdRow);
                                    ut.setSelected(cellsRange)
                                } else {
                                    rng && rng.selectNodeContents(endTdRow).select()
                                }
                            }
                        }
                    }
                });
                switchBorderColor(me, true)
            });
            domUtils.on(me.document, "mousemove", mouseMoveEvent);
            domUtils.on(me.document, "mouseout", function(evt) {
                var target = evt.target || evt.srcElement;
                if (target.tagName == "TABLE") {
                    toggleDraggableState(me, false, "", null)
                }
            });
            me.addListener("interlacetable", function(type, table, classList) {
                if (!table) {
                    return
                }
                var me = this,
                    rows = table.rows,
                    len = rows.length,
                    getClass = function(list, index, repeat) {
                        return list[index] ? list[index] : repeat ? list[index % list.length] : ""
                    };
                for (var i = 0; i < len; i++) {
                    rows[i].className = getClass(classList || me.options.classList, i, true)
                }
            });
            me.addListener("uninterlacetable", function(type, table) {
                if (!table) {
                    return
                }
                var me = this,
                    rows = table.rows,
                    classList = me.options.classList,
                    len = rows.length;
                for (var i = 0; i < len; i++) {
                    domUtils.removeClasses(rows[i], classList)
                }
            });
            me.addListener("mousedown", mouseDownEvent);
            me.addListener("mouseup", mouseUpEvent);
            domUtils.on(me.body, "dragstart", function(evt) {
                mouseUpEvent.call(me, "dragstart", evt)
            });
            me.addOutputRule(function(root) {
                utils.each(root.getNodesByTagName("div"), function(n) {
                    if (n.getAttr("id") == "ue_tableDragLine") {
                        n.parentNode.removeChild(n)
                    }
                })
            });
            var currentRowIndex = 0;
            me.addListener("mousedown", function() {
                currentRowIndex = 0
            });
            me.addListener("tabkeydown", function() {
                var range = this.selection.getRange(),
                    common = range.getCommonAncestor(true, true),
                    table = domUtils.findParentByTagName(common, "table");
                if (table) {
                    if (domUtils.findParentByTagName(common, "caption", true)) {
                        var cell = domUtils.getElementsByTagName(table, "th td");
                        if (cell && cell.length) {
                            range.setStart(cell[0], 0).setCursor(false, true)
                        }
                    } else {
                        var cell = domUtils.findParentByTagName(common, ["td", "th"], true),
                            ua = getUETable(cell);
                        currentRowIndex = cell.rowSpan > 1 ? currentRowIndex : ua.getCellInfo(cell).rowIndex;
                        var nextCell = ua.getTabNextCell(cell, currentRowIndex);
                        if (nextCell) {
                            if (isEmptyBlock(nextCell)) {
                                range.setStart(nextCell, 0).setCursor(false, true)
                            } else {
                                range.selectNodeContents(nextCell).select()
                            }
                        } else {
                            me.fireEvent("saveScene");
                            me.__hasEnterExecCommand = true;
                            this.execCommand("insertrownext");
                            me.__hasEnterExecCommand = false;
                            range = this.selection.getRange();
                            range.setStart(table.rows[table.rows.length - 1].cells[0], 0).setCursor();
                            me.fireEvent("saveScene")
                        }
                    }
                    return true
                }
            });
            browser.ie && me.addListener("selectionchange", function() {
                toggleDraggableState(this, false, "", null)
            });
            me.addListener("keydown", function(type, evt) {
                var me = this;
                var keyCode = evt.keyCode || evt.which;
                if (keyCode == 8 || keyCode == 46) {
                    return
                }
                var notCtrlKey = !evt.ctrlKey && !evt.metaKey && !evt.shiftKey && !evt.altKey;
                notCtrlKey && removeSelectedClass(domUtils.getElementsByTagName(me.body, "td"));
                var ut = getUETableBySelected(me);
                if (!ut) {
                    return
                }
                notCtrlKey && ut.clearSelected()
            });
            me.addListener("beforegetcontent", function() {
                switchBorderColor(this, false);
                browser.ie && utils.each(this.document.getElementsByTagName("caption"), function(ci) {
                    if (domUtils.isEmptyNode(ci)) {
                        ci.innerHTML = "&nbsp;"
                    }
                })
            });
            me.addListener("aftergetcontent", function() {
                switchBorderColor(this, true)
            });
            me.addListener("getAllHtml", function() {
                removeSelectedClass(me.document.getElementsByTagName("td"))
            });
            me.addListener("fullscreenchanged", function(type, fullscreen) {
                if (!fullscreen) {
                    var ratio = this.body.offsetWidth / document.body.offsetWidth,
                        tables = domUtils.getElementsByTagName(this.body, "table");
                    utils.each(tables, function(table) {
                        if (table.offsetWidth < me.body.offsetWidth) {
                            return false
                        }
                        var tds = domUtils.getElementsByTagName(table, "td"),
                            backWidths = [];
                        utils.each(tds, function(td) {
                            backWidths.push(td.offsetWidth)
                        });
                        for (var i = 0, td; td = tds[i]; i++) {
                            td.setAttribute("width", Math.floor(backWidths[i] * ratio))
                        }
                        table.setAttribute("width", Math.floor(getTableWidth(me, needIEHack, getDefaultValue(me))))
                    })
                }
            });
            var oldExecCommand = me.execCommand;
            me.execCommand = function(cmd, datatat) {
                var me = this,
                    args = arguments;
                cmd = cmd.toLowerCase();
                var ut = getUETableBySelected(me),
                    tds, range = new dom.Range(me.document),
                    cmdFun = me.commands[cmd] || UE.commands[cmd],
                    result;
                if (!cmdFun) {
                    return
                }
                if (ut && !commands[cmd] && !cmdFun.notNeedUndo && !me.__hasEnterExecCommand) {
                    me.__hasEnterExecCommand = true;
                    me.fireEvent("beforeexeccommand", cmd);
                    tds = ut.selectedTds;
                    var lastState = -2,
                        lastValue = -2,
                        value, state;
                    for (var i = 0, td; td = tds[i]; i++) {
                        if (isEmptyBlock(td)) {
                            range.setStart(td, 0).setCursor(false, true)
                        } else {
                            range.selectNode(td).select(true)
                        }
                        state = me.queryCommandState(cmd);
                        value = me.queryCommandValue(cmd);
                        if (state != -1) {
                            if (lastState !== state || lastValue !== value) {
                                me._ignoreContentChange = true;
                                result = oldExecCommand.apply(me, arguments);
                                me._ignoreContentChange = false
                            }
                            lastState = me.queryCommandState(cmd);
                            lastValue = me.queryCommandValue(cmd);
                            if (domUtils.isEmptyBlock(td)) {
                                domUtils.fillNode(me.document, td)
                            }
                        }
                    }
                    range.setStart(tds[0], 0).shrinkBoundary(true).setCursor(false, true);
                    me.fireEvent("contentchange");
                    me.fireEvent("afterexeccommand", cmd);
                    me.__hasEnterExecCommand = false;
                    me._selectionChange()
                } else {
                    result = oldExecCommand.apply(me, arguments)
                }
                return result
            }
        });

        function removeStyleSize(obj, replaceToProperty) {
            removeStyle(obj, "width", true);
            removeStyle(obj, "height", true)
        }
        function removeStyle(obj, styleName, replaceToProperty) {
            if (obj.style[styleName]) {
                replaceToProperty && obj.setAttribute(styleName, parseInt(obj.style[styleName], 10));
                obj.style[styleName] = ""
            }
        }
        function getParentTdOrTh(ele) {
            if (ele.tagName == "TD" || ele.tagName == "TH") {
                return ele
            }
            var td;
            if (td = domUtils.findParentByTagName(ele, "td", true) || domUtils.findParentByTagName(ele, "th", true)) {
                return td
            }
            return null
        }
        function isEmptyBlock(node) {
            var reg = new RegExp(domUtils.fillChar, "g");
            if (node[browser.ie ? "innerText" : "textContent"].replace(/^\s*$/, "").replace(reg, "").length > 0) {
                return 0
            }
            for (var n in dtd.$isNotEmpty) {
                if (node.getElementsByTagName(n).length) {
                    return 0
                }
            }
            return 1
        }
        function mouseCoords(evt) {
            if (evt.pageX || evt.pageY) {
                return {
                    x: evt.pageX,
                    y: evt.pageY
                }
            }
            return {
                x: evt.clientX + me.document.body.scrollLeft - me.document.body.clientLeft,
                y: evt.clientY + me.document.body.scrollTop - me.document.body.clientTop
            }
        }
        function mouseMoveEvent(evt) {
            if (isEditorDisabled()) {
                return
            }
            try {
                var target = getParentTdOrTh(evt.target || evt.srcElement),
                    pos;
                if (isInResizeBuffer) {
                    me.body.style.webkitUserSelect = "none";
                    if (Math.abs(userActionStatus.x - evt.clientX) > offsetOfTableCell || Math.abs(userActionStatus.y - evt.clientY) > offsetOfTableCell) {
                        clearTableDragTimer();
                        isInResizeBuffer = false;
                        singleClickState = 0;
                        tableBorderDrag(evt)
                    }
                }
                if (onDrag && dragTd) {
                    singleClickState = 0;
                    me.body.style.webkitUserSelect = "none";
                    me.selection.getNative()[browser.ie9below ? "empty" : "removeAllRanges"]();
                    pos = mouseCoords(evt);
                    toggleDraggableState(me, true, onDrag, pos, target);
                    if (onDrag == "h") {
                        dragLine.style.left = getPermissionX(dragTd, evt) + "px"
                    } else {
                        if (onDrag == "v") {
                            dragLine.style.top = getPermissionY(dragTd, evt) + "px"
                        }
                    }
                    return
                }
                if (target) {
                    if (me.fireEvent("excludetable", target) === true) {
                        return
                    }
                    pos = mouseCoords(evt);
                    var state = getRelation(target, pos),
                        table = domUtils.findParentByTagName(target, "table", true);
                    if (inTableSide(table, target, evt, true)) {
                        if (me.fireEvent("excludetable", table) === true) {
                            return
                        }
                        me.body.style.cursor = "url(" + me.options.cursorpath + "h.png),pointer"
                    } else {
                        if (inTableSide(table, target, evt)) {
                            if (me.fireEvent("excludetable", table) === true) {
                                return
                            }
                            me.body.style.cursor = "url(" + me.options.cursorpath + "v.png),pointer"
                        } else {
                            me.body.style.cursor = "text";
                            var curCell = target;
                            if (/\d/.test(state)) {
                                state = state.replace(/\d/, "");
                                target = getUETable(target).getPreviewCell(target, state == "v")
                            }
                            toggleDraggableState(me, target ? !! state : false, target ? state : "", pos, target)
                        }
                    }
                } else {
                    toggleDragButton(false, table, me)
                }
            } catch (e) {
                showError(e)
            }
        }
        var dragButtonTimer;

        function toggleDragButton(show, table, editor) {
            if (!show) {
                if (dragOver) {
                    return
                }
                dragButtonTimer = setTimeout(function() {
                    !dragOver && dragButton && dragButton.parentNode && dragButton.parentNode.removeChild(dragButton)
                }, 2000)
            } else {
                createDragButton(table, editor)
            }
        }
        function createDragButton(table, editor) {
            var pos = domUtils.getXY(table),
                doc = table.ownerDocument;
            if (dragButton && dragButton.parentNode) {
                return dragButton
            }
            dragButton = doc.createElement("div");
            dragButton.contentEditable = false;
            dragButton.innerHTML = "";
            dragButton.style.cssText = "width:15px;height:15px;background-image:url(" + editor.options.UEDITOR_HOME_URL + "dialogs/table/dragicon.png);position: absolute;cursor:move;top:" + (pos.y - 15) + "px;left:" + (pos.x) + "px;";
            domUtils.unSelectable(dragButton);
            dragButton.onmouseover = function(evt) {
                dragOver = true
            };
            dragButton.onmouseout = function(evt) {
                dragOver = false
            };
            domUtils.on(dragButton, "click", function(type, evt) {
                doClick(evt, this)
            });
            domUtils.on(dragButton, "dblclick", function(type, evt) {
                doDblClick(evt)
            });
            domUtils.on(dragButton, "dragstart", function(type, evt) {
                domUtils.preventDefault(evt)
            });
            var timer;

            function doClick(evt, button) {
                clearTimeout(timer);
                timer = setTimeout(function() {
                    editor.fireEvent("tableClicked", table, button)
                }, 300)
            }
            function doDblClick(evt) {
                clearTimeout(timer);
                var ut = getUETable(table),
                    start = table.rows[0].cells[0],
                    end = ut.getLastCell(),
                    range = ut.getCellsRange(start, end);
                editor.selection.getRange().setStart(start, 0).setCursor(false, true);
                ut.setSelected(range)
            }
            doc.body.appendChild(dragButton)
        }
        function inTableSide(table, cell, evt, top) {
            var pos = mouseCoords(evt),
                state = getRelation(cell, pos);
            if (top) {
                var caption = table.getElementsByTagName("caption")[0],
                    capHeight = caption ? caption.offsetHeight : 0;
                return (state == "v1") && ((pos.y - domUtils.getXY(table).y - capHeight) < 8)
            } else {
                return (state == "h1") && ((pos.x - domUtils.getXY(table).x) < 8)
            }
        }
        function getPermissionX(dragTd, evt) {
            var ut = getUETable(dragTd);
            if (ut) {
                var preTd = ut.getSameEndPosCells(dragTd, "x")[0],
                    nextTd = ut.getSameStartPosXCells(dragTd)[0],
                    mouseX = mouseCoords(evt).x,
                    left = (preTd ? domUtils.getXY(preTd).x : domUtils.getXY(ut.table).x) + 20,
                    right = nextTd ? domUtils.getXY(nextTd).x + nextTd.offsetWidth - 20 : (me.body.offsetWidth + 5 || parseInt(domUtils.getComputedStyle(me.body, "width"), 10));
                left += cellMinWidth;
                right -= cellMinWidth;
                return mouseX < left ? left : mouseX > right ? right : mouseX
            }
        }
        function getPermissionY(dragTd, evt) {
            try {
                var top = domUtils.getXY(dragTd).y,
                    mousePosY = mouseCoords(evt).y;
                return mousePosY < top ? top : mousePosY
            } catch (e) {
                showError(e)
            }
        }
        function toggleDraggableState(editor, draggable, dir, mousePos, cell) {
            try {
                editor.body.style.cursor = dir == "h" ? "col-resize" : dir == "v" ? "row-resize" : "text";
                if (browser.ie) {
                    if (dir && !mousedown && !getUETableBySelected(editor)) {
                        getDragLine(editor, editor.document);
                        showDragLineAt(dir, cell)
                    } else {
                        hideDragLine(editor)
                    }
                }
                onBorder = draggable
            } catch (e) {
                showError(e)
            }
        }
        function getResizeLineByUETable() {
            var lineId = "_UETableResizeLine",
                line = this.document.getElementById(lineId);
            if (!line) {
                line = this.document.createElement("div");
                line.id = lineId;
                line.contnetEditable = false;
                line.setAttribute("unselectable", "on");
                var styles = {
                    width: 2 * cellBorderWidth + 1 + "px",
                    position: "absolute",
                    "z-index": 100000,
                    cursor: "col-resize",
                    background: "red",
                    display: "none"
                };
                line.onmouseout = function() {
                    this.style.display = "none"
                };
                utils.extend(line.style, styles);
                this.document.body.appendChild(line)
            }
            return line
        }
        function updateResizeLine(cell, uetable) {
            var line = getResizeLineByUETable.call(this),
                table = uetable.table,
                styles = {
                    top: domUtils.getXY(table).y + "px",
                    left: domUtils.getXY(cell).x + cell.offsetWidth - cellBorderWidth + "px",
                    display: "block",
                    height: table.offsetHeight + "px"
                };
            utils.extend(line.style, styles)
        }
        function showResizeLine(cell) {
            var uetable = getUETable(cell);
            updateResizeLine.call(this, cell, uetable)
        }
        function getRelation(ele, mousePos) {
            var elePos = domUtils.getXY(ele);
            if (!elePos) {
                return ""
            }
            if (elePos.x + ele.offsetWidth - mousePos.x < cellBorderWidth) {
                return "h"
            }
            if (mousePos.x - elePos.x < cellBorderWidth) {
                return "h1"
            }
            if (elePos.y + ele.offsetHeight - mousePos.y < cellBorderWidth) {
                return "v"
            }
            if (mousePos.y - elePos.y < cellBorderWidth) {
                return "v1"
            }
            return ""
        }
        function mouseDownEvent(type, evt) {
            if (isEditorDisabled()) {
                return
            }
            userActionStatus = {
                x: evt.clientX,
                y: evt.clientY
            };
            if (evt.button == 2) {
                var ut = getUETableBySelected(me),
                    flag = false;
                if (ut) {
                    var td = getTargetTd(me, evt);
                    utils.each(ut.selectedTds, function(ti) {
                        if (ti === td) {
                            flag = true
                        }
                    });
                    if (!flag) {
                        removeSelectedClass(domUtils.getElementsByTagName(me.body, "th td"));
                        ut.clearSelected()
                    } else {
                        td = ut.selectedTds[0];
                        setTimeout(function() {
                            me.selection.getRange().setStart(td, 0).setCursor(false, true)
                        }, 0)
                    }
                }
            } else {
                tableClickHander(evt)
            }
        }
        function clearTableTimer() {
            tabTimer && clearTimeout(tabTimer);
            tabTimer = null
        }
        function tableDbclickHandler(evt) {
            singleClickState = 0;
            evt = evt || me.window.event;
            var target = getParentTdOrTh(evt.target || evt.srcElement);
            if (target) {
                var h;
                if (h = getRelation(target, mouseCoords(evt))) {
                    hideDragLine(me);
                    if (h == "h1") {
                        h = "h";
                        if (inTableSide(domUtils.findParentByTagName(target, "table"), target, evt)) {
                            me.execCommand("adaptbywindow")
                        } else {
                            target = getUETable(target).getPreviewCell(target);
                            if (target) {
                                var rng = me.selection.getRange();
                                rng.selectNodeContents(target).setCursor(true, true)
                            }
                        }
                    }
                    if (h == "h") {
                        var ut = getUETable(target),
                            table = ut.table,
                            cells = getCellsByMoveBorder(target, table, true);
                        cells = extractArray(cells, "left");
                        ut.width = ut.offsetWidth;
                        var oldWidth = [],
                            newWidth = [];
                        utils.each(cells, function(cell) {
                            oldWidth.push(cell.offsetWidth)
                        });
                        utils.each(cells, function(cell) {
                            cell.removeAttribute("width")
                        });
                        window.setTimeout(function() {
                            var changeable = true;
                            utils.each(cells, function(cell, index) {
                                var width = cell.offsetWidth;
                                if (width > oldWidth[index]) {
                                    changeable = false;
                                    return false
                                }
                                newWidth.push(width)
                            });
                            var change = changeable ? newWidth : oldWidth;
                            utils.each(cells, function(cell, index) {
                                cell.width = change[index] - getTabcellSpace()
                            })
                        }, 0)
                    }
                }
            }
        }
        function tableClickHander(evt) {
            removeSelectedClass(domUtils.getElementsByTagName(me.body, "td th"));
            utils.each(me.document.getElementsByTagName("table"), function(t) {
                t.ueTable = null
            });
            startTd = getTargetTd(me, evt);
            if (!startTd) {
                return
            }
            var table = domUtils.findParentByTagName(startTd, "table", true);
            ut = getUETable(table);
            ut && ut.clearSelected();
            if (!onBorder) {
                me.document.body.style.webkitUserSelect = "";
                mousedown = true;
                me.addListener("mouseover", mouseOverEvent)
            } else {
                borderActionHandler(evt)
            }
        }
        function borderActionHandler(evt) {
            if (browser.ie) {
                evt = reconstruct(evt)
            }
            clearTableDragTimer();
            isInResizeBuffer = true;
            tableDragTimer = setTimeout(function() {
                tableBorderDrag(evt)
            }, dblclickTime)
        }
        function extractArray(originArr, key) {
            var result = [],
                tmp = null;
            for (var i = 0, len = originArr.length; i < len; i++) {
                tmp = originArr[i][key];
                if (tmp) {
                    result.push(tmp)
                }
            }
            return result
        }
        function clearTableDragTimer() {
            tableDragTimer && clearTimeout(tableDragTimer);
            tableDragTimer = null
        }
        function reconstruct(obj) {
            var attrs = ["pageX", "pageY", "clientX", "clientY", "srcElement", "target"],
                newObj = {};
            if (obj) {
                for (var i = 0, key, val; key = attrs[i]; i++) {
                    val = obj[key];
                    val && (newObj[key] = val)
                }
            }
            return newObj
        }
        function tableBorderDrag(evt) {
            isInResizeBuffer = false;
            startTd = evt.target || evt.srcElement;
            if (!startTd) {
                return
            }
            var state = getRelation(startTd, mouseCoords(evt));
            if (/\d/.test(state)) {
                state = state.replace(/\d/, "");
                startTd = getUETable(startTd).getPreviewCell(startTd, state == "v")
            }
            hideDragLine(me);
            getDragLine(me, me.document);
            me.fireEvent("saveScene");
            showDragLineAt(state, startTd);
            mousedown = true;
            onDrag = state;
            dragTd = startTd
        }
        function mouseUpEvent(type, evt) {
            if (isEditorDisabled()) {
                return
            }
            clearTableDragTimer();
            isInResizeBuffer = false;
            if (onBorder) {
                singleClickState = ++singleClickState % 3;
                userActionStatus = {
                    x: evt.clientX,
                    y: evt.clientY
                };
                tableResizeTimer = setTimeout(function() {
                    singleClickState > 0 && singleClickState--
                }, dblclickTime);
                if (singleClickState === 2) {
                    singleClickState = 0;
                    tableDbclickHandler(evt);
                    return
                }
            }
            if (evt.button == 2) {
                return
            }
            var me = this;
            var range = me.selection.getRange(),
                start = domUtils.findParentByTagName(range.startContainer, "table", true),
                end = domUtils.findParentByTagName(range.endContainer, "table", true);
            if (start || end) {
                if (start === end) {
                    start = domUtils.findParentByTagName(range.startContainer, ["td", "th", "caption"], true);
                    end = domUtils.findParentByTagName(range.endContainer, ["td", "th", "caption"], true);
                    if (start !== end) {
                        me.selection.clearRange()
                    }
                } else {
                    me.selection.clearRange()
                }
            }
            mousedown = false;
            me.document.body.style.webkitUserSelect = "";
            if (onDrag && dragTd) {
                me.selection.getNative()[browser.ie9below ? "empty" : "removeAllRanges"]();
                singleClickState = 0;
                dragLine = me.document.getElementById("ue_tableDragLine");
                if (dragLine) {
                    var dragTdPos = domUtils.getXY(dragTd),
                        dragLinePos = domUtils.getXY(dragLine);
                    switch (onDrag) {
                        case "h":
                            changeColWidth(dragTd, dragLinePos.x - dragTdPos.x);
                            break;
                        case "v":
                            changeRowHeight(dragTd, dragLinePos.y - dragTdPos.y - dragTd.offsetHeight);
                            break;
                        default:
                    }
                    onDrag = "";
                    dragTd = null;
                    hideDragLine(me);
                    me.fireEvent("saveScene");
                    return
                }
            }
            if (!startTd) {
                var target = domUtils.findParentByTagName(evt.target || evt.srcElement, "td", true);
                if (!target) {
                    target = domUtils.findParentByTagName(evt.target || evt.srcElement, "th", true)
                }
                if (target && (target.tagName == "TD" || target.tagName == "TH")) {
                    if (me.fireEvent("excludetable", target) === true) {
                        return
                    }
                    range = new dom.Range(me.document);
                    range.setStart(target, 0).setCursor(false, true)
                }
            } else {
                var ut = getUETable(startTd),
                    cell = ut ? ut.selectedTds[0] : null;
                if (cell) {
                    range = new dom.Range(me.document);
                    if (domUtils.isEmptyBlock(cell)) {
                        range.setStart(cell, 0).setCursor(false, true)
                    } else {
                        range.selectNodeContents(cell).shrinkBoundary().setCursor(false, true)
                    }
                } else {
                    range = me.selection.getRange().shrinkBoundary();
                    if (!range.collapsed) {
                        var start = domUtils.findParentByTagName(range.startContainer, ["td", "th"], true),
                            end = domUtils.findParentByTagName(range.endContainer, ["td", "th"], true);
                        if (start && !end || !start && end || start && end && start !== end) {
                            range.setCursor(false, true)
                        }
                    }
                }
                startTd = null;
                me.removeListener("mouseover", mouseOverEvent)
            }
            me._selectionChange(250, evt)
        }
        function mouseOverEvent(type, evt) {
            if (isEditorDisabled()) {
                return
            }
            var me = this,
                tar = evt.target || evt.srcElement;
            currentTd = domUtils.findParentByTagName(tar, "td", true) || domUtils.findParentByTagName(tar, "th", true);
            if (startTd && currentTd && ((startTd.tagName == "TD" && currentTd.tagName == "TD") || (startTd.tagName == "TH" && currentTd.tagName == "TH")) && domUtils.findParentByTagName(startTd, "table") == domUtils.findParentByTagName(currentTd, "table")) {
                var ut = getUETable(currentTd);
                if (startTd != currentTd) {
                    me.document.body.style.webkitUserSelect = "none";
                    me.selection.getNative()[browser.ie9below ? "empty" : "removeAllRanges"]();
                    var range = ut.getCellsRange(startTd, currentTd);
                    ut.setSelected(range)
                } else {
                    me.document.body.style.webkitUserSelect = "";
                    ut.clearSelected()
                }
            }
            evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false)
        }
        function setCellHeight(cell, height, backHeight) {
            var lineHight = parseInt(domUtils.getComputedStyle(cell, "line-height"), 10),
                tmpHeight = backHeight + height;
            height = tmpHeight < lineHight ? lineHight : tmpHeight;
            if (cell.style.height) {
                cell.style.height = ""
            }
            cell.rowSpan == 1 ? cell.setAttribute("height", height) : (cell.removeAttribute && cell.removeAttribute("height"))
        }
        function getWidth(cell) {
            if (!cell) {
                return 0
            }
            return parseInt(domUtils.getComputedStyle(cell, "width"), 10)
        }
        function changeColWidth(cell, changeValue) {
            var ut = getUETable(cell);
            if (ut) {
                var table = ut.table,
                    cells = getCellsByMoveBorder(cell, table);
                table.style.width = "";
                table.removeAttribute("width");
                changeValue = correctChangeValue(changeValue, cell, cells);
                if (cell.nextSibling) {
                    var i = 0;
                    utils.each(cells, function(cellGroup) {
                        cellGroup.left.width = (+cellGroup.left.width) + changeValue;
                        cellGroup.right && (cellGroup.right.width = (+cellGroup.right.width) - changeValue)
                    })
                } else {
                    utils.each(cells, function(cellGroup) {
                        cellGroup.left.width -= -changeValue
                    })
                }
            }
        }
        function isEditorDisabled() {
            return me.body.contentEditable === "false"
        }
        function changeRowHeight(td, changeValue) {
            if (Math.abs(changeValue) < 10) {
                return
            }
            var ut = getUETable(td);
            if (ut) {
                var cells = ut.getSameEndPosCells(td, "y"),
                    backHeight = cells[0] ? cells[0].offsetHeight : 0;
                for (var i = 0, cell; cell = cells[i++];) {
                    setCellHeight(cell, changeValue, backHeight)
                }
            }
        }
        function getCellsByMoveBorder(cell, table, isContainMergeCell) {
            if (!table) {
                table = domUtils.findParentByTagName(cell, "table")
            }
            if (!table) {
                return null
            }
            var index = domUtils.getNodeIndex(cell),
                temp = cell,
                rows = table.rows,
                colIndex = 0;
            while (temp) {
                if (temp.nodeType === 1) {
                    colIndex += (temp.colSpan || 1)
                }
                temp = temp.previousSibling
            }
            temp = null;
            var borderCells = [];
            utils.each(rows, function(tabRow) {
                var cells = tabRow.cells,
                    currIndex = 0;
                utils.each(cells, function(tabCell) {
                    currIndex += (tabCell.colSpan || 1);
                    if (currIndex === colIndex) {
                        borderCells.push({
                            left: tabCell,
                            right: tabCell.nextSibling || null
                        });
                        return false
                    } else {
                        if (currIndex > colIndex) {
                            if (isContainMergeCell) {
                                borderCells.push({
                                    left: tabCell
                                })
                            }
                            return false
                        }
                    }
                })
            });
            return borderCells
        }
        function getMinWidthByTableCells(cells) {
            var minWidth = Number.MAX_VALUE;
            for (var i = 0, curCell; curCell = cells[i]; i++) {
                minWidth = Math.min(minWidth, curCell.width || getTableCellWidth(curCell))
            }
            return minWidth
        }
        function correctChangeValue(changeValue, relatedCell, cells) {
            changeValue -= getTabcellSpace();
            if (changeValue < 0) {
                return 0
            }
            changeValue -= getTableCellWidth(relatedCell);
            var direction = changeValue < 0 ? "left" : "right";
            changeValue = Math.abs(changeValue);
            utils.each(cells, function(cellGroup) {
                var curCell = cellGroup[direction];
                if (curCell) {
                    changeValue = Math.min(changeValue, getTableCellWidth(curCell) - cellMinWidth)
                }
            });
            changeValue = changeValue < 0 ? 0 : changeValue;
            return direction === "left" ? -changeValue : changeValue
        }
        function getTableCellWidth(cell) {
            var width = 0,
                offset = 0,
                width = cell.offsetWidth - getTabcellSpace();
            if (!cell.nextSibling) {
                width -= getTableCellOffset(cell)
            }
            width = width < 0 ? 0 : width;
            try {
                cell.width = width
            } catch (e) {}
            return width
        }
        function getTableCellOffset(cell) {
            tab = domUtils.findParentByTagName(cell, "table", false);
            if (tab.offsetVal === undefined) {
                var prev = cell.previousSibling;
                if (prev) {
                    tab.offsetVal = cell.offsetWidth - prev.offsetWidth === UT.borderWidth ? UT.borderWidth : 0
                } else {
                    tab.offsetVal = 0
                }
            }
            return tab.offsetVal
        }
        function getTabcellSpace() {
            if (UT.tabcellSpace === undefined) {
                var cell = null,
                    tab = me.document.createElement("table"),
                    tbody = me.document.createElement("tbody"),
                    trow = me.document.createElement("tr"),
                    tabcell = me.document.createElement("td"),
                    mirror = null;
                tabcell.style.cssText = "border: 0;";
                tabcell.width = 1;
                trow.appendChild(tabcell);
                trow.appendChild(mirror = tabcell.cloneNode(false));
                tbody.appendChild(trow);
                tab.appendChild(tbody);
                tab.style.cssText = "visibility: hidden;";
                me.body.appendChild(tab);
                UT.paddingSpace = tabcell.offsetWidth - 1;
                var tmpTabWidth = tab.offsetWidth;
                tabcell.style.cssText = "";
                mirror.style.cssText = "";
                UT.borderWidth = (tab.offsetWidth - tmpTabWidth) / 3;
                UT.tabcellSpace = UT.paddingSpace + UT.borderWidth;
                me.body.removeChild(tab)
            }
            getTabcellSpace = function() {
                return UT.tabcellSpace
            };
            return UT.tabcellSpace
        }
        function getDragLine(editor, doc) {
            if (mousedown) {
                return
            }
            dragLine = editor.document.createElement("div");
            domUtils.setAttributes(dragLine, {
                id: "ue_tableDragLine",
                unselectable: "on",
                contenteditable: false,
                "onresizestart": "return false",
                "ondragstart": "return false",
                "onselectstart": "return false",
                style: "background-color:blue;position:absolute;padding:0;margin:0;background-image:none;border:0px none;opacity:0;filter:alpha(opacity=0)"
            });
            editor.body.appendChild(dragLine)
        }
        function hideDragLine(editor) {
            if (mousedown) {
                return
            }
            var line;
            while (line = editor.document.getElementById("ue_tableDragLine")) {
                domUtils.remove(line)
            }
        }
        function showDragLineAt(state, cell) {
            if (!cell) {
                return
            }
            var table = domUtils.findParentByTagName(cell, "table"),
                caption = table.getElementsByTagName("caption"),
                width = table.offsetWidth,
                height = table.offsetHeight - (caption.length > 0 ? caption[0].offsetHeight : 0),
                tablePos = domUtils.getXY(table),
                cellPos = domUtils.getXY(cell),
                css;
            switch (state) {
                case "h":
                    css = "height:" + height + "px;top:" + (tablePos.y + (caption.length > 0 ? caption[0].offsetHeight : 0)) + "px;left:" + (cellPos.x + cell.offsetWidth);
                    dragLine.style.cssText = css + "px;position: absolute;display:block;background-color:blue;width:1px;border:0; color:blue;opacity:.3;filter:alpha(opacity=30)";
                    break;
                case "v":
                    css = "width:" + width + "px;left:" + tablePos.x + "px;top:" + (cellPos.y + cell.offsetHeight);
                    dragLine.style.cssText = css + "px;overflow:hidden;position: absolute;display:block;background-color:blue;height:1px;border:0;color:blue;opacity:.2;filter:alpha(opacity=20)";
                    break;
                default:
            }
        }
        function switchBorderColor(editor, flag) {
            var tableArr = domUtils.getElementsByTagName(editor.body, "table"),
                color;
            for (var i = 0, node; node = tableArr[i++];) {
                var td = domUtils.getElementsByTagName(node, "td");
                if (td[0]) {
                    if (flag) {
                        color = (td[0].style.borderColor).replace(/\s/g, "");
                        if (/(#ffffff)|(rgb\(255,255,255\))/ig.test(color)) {
                            domUtils.addClass(node, "noBorderTable")
                        }
                    } else {
                        domUtils.removeClasses(node, "noBorderTable")
                    }
                }
            }
        }
        function getTableWidth(editor, needIEHack, defaultValue) {
            var body = editor.body;
            return body.offsetWidth - (needIEHack ? parseInt(domUtils.getComputedStyle(body, "margin-left"), 10) * 2 : 0) - defaultValue.tableBorder * 2 - (editor.options.offsetWidth || 0)
        }
        function getTargetTd(editor, evt) {
            var target = domUtils.findParentByTagName(evt.target || evt.srcElement, ["td", "th"], true),
                dir = null;
            if (!target) {
                return null
            }
            dir = getRelation(target, mouseCoords(evt));
            if (!target) {
                return null
            }
            if (dir === "h1" && target.previousSibling) {
                var position = domUtils.getXY(target),
                    cellWidth = target.offsetWidth;
                if (Math.abs(position.x + cellWidth - evt.clientX) > cellWidth / 3) {
                    target = target.previousSibling
                }
            } else {
                if (dir === "v1" && target.parentNode.previousSibling) {
                    var position = domUtils.getXY(target),
                        cellHeight = target.offsetHeight;
                    if (Math.abs(position.y + cellHeight - evt.clientY) > cellHeight / 3) {
                        target = target.parentNode.previousSibling.firstChild
                    }
                }
            }
            return target && !(editor.fireEvent("excludetable", target) === true) ? target : null
        }
    };
    UE.UETable.prototype.sortTable = function(sortByCellIndex, compareFn) {
        var table = this.table,
            rows = table.rows,
            trArray = [],
            flag = rows[0].cells[0].tagName === "TH",
            lastRowIndex = 0;
        if (this.selectedTds.length) {
            var range = this.cellsRange,
                len = range.endRowIndex + 1;
            for (var i = range.beginRowIndex; i < len; i++) {
                trArray[i] = rows[i]
            }
            trArray.splice(0, range.beginRowIndex);
            lastRowIndex = (range.endRowIndex + 1) === this.rowsNum ? 0 : range.endRowIndex + 1
        } else {
            for (var i = 0, len = rows.length; i < len; i++) {
                trArray[i] = rows[i]
            }
        }
        var Fn = {
            "reversecurrent": function(td1, td2) {
                return 1
            },
            "orderbyasc": function(td1, td2) {
                var value1 = td1.innerText || td1.textContent,
                    value2 = td2.innerText || td2.textContent;
                return value1.localeCompare(value2)
            },
            "reversebyasc": function(td1, td2) {
                var value1 = td1.innerHTML,
                    value2 = td2.innerHTML;
                return value2.localeCompare(value1)
            },
            "orderbynum": function(td1, td2) {
                var value1 = td1[browser.ie ? "innerText" : "textContent"].match(/\d+/),
                    value2 = td2[browser.ie ? "innerText" : "textContent"].match(/\d+/);
                if (value1) {
                    value1 = +value1[0]
                }
                if (value2) {
                    value2 = +value2[0]
                }
                return (value1 || 0) - (value2 || 0)
            },
            "reversebynum": function(td1, td2) {
                var value1 = td1[browser.ie ? "innerText" : "textContent"].match(/\d+/),
                    value2 = td2[browser.ie ? "innerText" : "textContent"].match(/\d+/);
                if (value1) {
                    value1 = +value1[0]
                }
                if (value2) {
                    value2 = +value2[0]
                }
                return (value2 || 0) - (value1 || 0)
            }
        };
        table.setAttribute("data-sort-type", compareFn && typeof compareFn === "string" && Fn[compareFn] ? compareFn : "");
        flag && trArray.splice(0, 1);
        trArray = utils.sort(trArray, function(tr1, tr2) {
            var result;
            if (compareFn && typeof compareFn === "function") {
                result = compareFn.call(this, tr1.cells[sortByCellIndex], tr2.cells[sortByCellIndex])
            } else {
                if (compareFn && typeof compareFn === "number") {
                    result = 1
                } else {
                    if (compareFn && typeof compareFn === "string" && Fn[compareFn]) {
                        result = Fn[compareFn].call(this, tr1.cells[sortByCellIndex], tr2.cells[sortByCellIndex])
                    } else {
                        result = Fn["orderbyasc"].call(this, tr1.cells[sortByCellIndex], tr2.cells[sortByCellIndex])
                    }
                }
            }
            return result
        });
        var fragment = table.ownerDocument.createDocumentFragment();
        for (var j = 0, len = trArray.length; j < len; j++) {
            fragment.appendChild(trArray[j])
        }
        var tbody = table.getElementsByTagName("tbody")[0];
        if (!lastRowIndex) {
            tbody.appendChild(fragment)
        } else {
            tbody.insertBefore(fragment, rows[lastRowIndex - range.endRowIndex + range.beginRowIndex - 1])
        }
    };
    UE.plugins["tablesort"] = function() {
        var me = this,
            UT = UE.UETable,
            getUETable = function(tdOrTable) {
                return UT.getUETable(tdOrTable)
            },
            getTableItemsByRange = function(editor) {
                return UT.getTableItemsByRange(editor)
            };
        me.ready(function() {
            utils.cssRule("tablesort", "table.sortEnabled tr.firstRow th,table.sortEnabled tr.firstRow td{padding-right:20px;background-repeat: no-repeat;background-position: center right;" + "   background-image:url(" + me.options.themePath + me.options.theme + "/images/sortable.png);}", me.document);
            me.addListener("afterexeccommand", function(type, cmd) {
                if (cmd == "mergeright" || cmd == "mergedown" || cmd == "mergecells") {
                    this.execCommand("disablesort")
                }
            })
        });
        UE.commands["sorttable"] = {
            queryCommandState: function() {
                var me = this,
                    tableItems = getTableItemsByRange(me);
                if (!tableItems.cell) {
                    return -1
                }
                var table = tableItems.table,
                    cells = table.getElementsByTagName("td");
                for (var i = 0, cell; cell = cells[i++];) {
                    if (cell.rowSpan != 1 || cell.colSpan != 1) {
                        return -1
                    }
                }
                return 0
            },
            execCommand: function(cmd, fn) {
                var me = this,
                    range = me.selection.getRange(),
                    bk = range.createBookmark(true),
                    tableItems = getTableItemsByRange(me),
                    cell = tableItems.cell,
                    ut = getUETable(tableItems.table),
                    cellInfo = ut.getCellInfo(cell);
                ut.sortTable(cellInfo.cellIndex, fn);
                range.moveToBookmark(bk);
                try {
                    range.select()
                } catch (e) {}
            }
        };
        UE.commands["enablesort"] = UE.commands["disablesort"] = {
            queryCommandState: function(cmd) {
                var table = getTableItemsByRange(this).table;
                if (table && cmd == "enablesort") {
                    var cells = domUtils.getElementsByTagName(table, "th td");
                    for (var i = 0; i < cells.length; i++) {
                        if (cells[i].getAttribute("colspan") > 1 || cells[i].getAttribute("rowspan") > 1) {
                            return -1
                        }
                    }
                }
                return !table ? -1 : cmd == "enablesort" ^ table.getAttribute("data-sort") != "sortEnabled" ? -1 : 0
            },
            execCommand: function(cmd) {
                var table = getTableItemsByRange(this).table;
                table.setAttribute("data-sort", cmd == "enablesort" ? "sortEnabled" : "sortDisabled");
                cmd == "enablesort" ? domUtils.addClass(table, "sortEnabled") : domUtils.removeClasses(table, "sortEnabled")
            }
        }
    };
    UE.plugins["contextmenu"] = function() {
        var me = this;
        me.setOpt("enableContextMenu", true);
        if (me.getOpt("enableContextMenu") === false) {
            return
        }
        var lang = me.getLang("contextMenu"),
            menu, items = me.options.contextMenu || [{
                label: lang["selectall"],
                cmdName: "selectall"
            }, {
                label: lang.cleardoc,
                cmdName: "cleardoc",
                exec: function() {
                    if (confirm(lang.confirmclear)) {
                        this.execCommand("cleardoc")
                    }
                }
            }, "-",
                {
                    label: lang.unlink,
                    cmdName: "unlink"
                }, "-",
                {
                    group: lang.paragraph,
                    icon: "justifyjustify",
                    subMenu: [{
                        label: lang.justifyleft,
                        cmdName: "justify",
                        value: "left"
                    }, {
                        label: lang.justifyright,
                        cmdName: "justify",
                        value: "right"
                    }, {
                        label: lang.justifycenter,
                        cmdName: "justify",
                        value: "center"
                    }, {
                        label: lang.justifyjustify,
                        cmdName: "justify",
                        value: "justify"
                    }]
                }, "-",
                {
                    group: lang.table,
                    icon: "table",
                    subMenu: [{
                        label: lang.inserttable,
                        cmdName: "inserttable"
                    }, {
                        label: lang.deletetable,
                        cmdName: "deletetable"
                    }, "-",
                        {
                            label: lang.deleterow,
                            cmdName: "deleterow"
                        }, {
                            label: lang.deletecol,
                            cmdName: "deletecol"
                        }, {
                            label: lang.insertcol,
                            cmdName: "insertcol"
                        }, {
                            label: lang.insertcolnext,
                            cmdName: "insertcolnext"
                        }, {
                            label: lang.insertrow,
                            cmdName: "insertrow"
                        }, {
                            label: lang.insertrownext,
                            cmdName: "insertrownext"
                        }, "-",
                        {
                            label: lang.insertcaption,
                            cmdName: "insertcaption"
                        }, {
                            label: lang.deletecaption,
                            cmdName: "deletecaption"
                        }, {
                            label: lang.inserttitle,
                            cmdName: "inserttitle"
                        }, {
                            label: lang.deletetitle,
                            cmdName: "deletetitle"
                        }, {
                            label: lang.inserttitlecol,
                            cmdName: "inserttitlecol"
                        }, {
                            label: lang.deletetitlecol,
                            cmdName: "deletetitlecol"
                        }, "-",
                        {
                            label: lang.mergecells,
                            cmdName: "mergecells"
                        }, {
                            label: lang.mergeright,
                            cmdName: "mergeright"
                        }, {
                            label: lang.mergedown,
                            cmdName: "mergedown"
                        }, "-",
                        {
                            label: lang.splittorows,
                            cmdName: "splittorows"
                        }, {
                            label: lang.splittocols,
                            cmdName: "splittocols"
                        }, {
                            label: lang.splittocells,
                            cmdName: "splittocells"
                        }, "-",
                        {
                            label: lang.averageDiseRow,
                            cmdName: "averagedistributerow"
                        }, {
                            label: lang.averageDisCol,
                            cmdName: "averagedistributecol"
                        }, "-",
                        {
                            label: lang.edittd,
                            cmdName: "edittd",
                            exec: function() {
                                if (UE.ui["edittd"]) {
                                    new UE.ui["edittd"](this)
                                }
                                this.getDialog("edittd").open()
                            }
                        }, {
                            label: lang.edittable,
                            cmdName: "edittable",
                            exec: function() {
                                if (UE.ui["edittable"]) {
                                    new UE.ui["edittable"](this)
                                }
                                this.getDialog("edittable").open()
                            }
                        }, {
                            label: lang.setbordervisible,
                            cmdName: "setbordervisible"
                        }]
                }, {
                    group: lang.tablesort,
                    icon: "tablesort",
                    subMenu: [{
                        label: lang.enablesort,
                        cmdName: "enablesort"
                    }, {
                        label: lang.disablesort,
                        cmdName: "disablesort"
                    }, "-",
                        {
                            label: lang.reversecurrent,
                            cmdName: "sorttable",
                            value: "reversecurrent"
                        }, {
                            label: lang.orderbyasc,
                            cmdName: "sorttable",
                            value: "orderbyasc"
                        }, {
                            label: lang.reversebyasc,
                            cmdName: "sorttable",
                            value: "reversebyasc"
                        }, {
                            label: lang.orderbynum,
                            cmdName: "sorttable",
                            value: "orderbynum"
                        }, {
                            label: lang.reversebynum,
                            cmdName: "sorttable",
                            value: "reversebynum"
                        }]
                }, {
                    group: lang.borderbk,
                    icon: "borderBack",
                    subMenu: [{
                        label: lang.setcolor,
                        cmdName: "interlacetable",
                        exec: function() {
                            this.execCommand("interlacetable")
                        }
                    }, {
                        label: lang.unsetcolor,
                        cmdName: "uninterlacetable",
                        exec: function() {
                            this.execCommand("uninterlacetable")
                        }
                    }, {
                        label: lang.setbackground,
                        cmdName: "settablebackground",
                        exec: function() {
                            this.execCommand("settablebackground", {
                                repeat: true,
                                colorList: ["#bbb", "#ccc"]
                            })
                        }
                    }, {
                        label: lang.unsetbackground,
                        cmdName: "cleartablebackground",
                        exec: function() {
                            this.execCommand("cleartablebackground")
                        }
                    }, {
                        label: lang.redandblue,
                        cmdName: "settablebackground",
                        exec: function() {
                            this.execCommand("settablebackground", {
                                repeat: true,
                                colorList: ["red", "blue"]
                            })
                        }
                    }, {
                        label: lang.threecolorgradient,
                        cmdName: "settablebackground",
                        exec: function() {
                            this.execCommand("settablebackground", {
                                repeat: true,
                                colorList: ["#aaa", "#bbb", "#ccc"]
                            })
                        }
                    }]
                }, {
                    group: lang.aligntd,
                    icon: "aligntd",
                    subMenu: [{
                        cmdName: "cellalignment",
                        value: {
                            align: "left",
                            vAlign: "top"
                        }
                    }, {
                        cmdName: "cellalignment",
                        value: {
                            align: "center",
                            vAlign: "top"
                        }
                    }, {
                        cmdName: "cellalignment",
                        value: {
                            align: "right",
                            vAlign: "top"
                        }
                    }, {
                        cmdName: "cellalignment",
                        value: {
                            align: "left",
                            vAlign: "middle"
                        }
                    }, {
                        cmdName: "cellalignment",
                        value: {
                            align: "center",
                            vAlign: "middle"
                        }
                    }, {
                        cmdName: "cellalignment",
                        value: {
                            align: "right",
                            vAlign: "middle"
                        }
                    }, {
                        cmdName: "cellalignment",
                        value: {
                            align: "left",
                            vAlign: "bottom"
                        }
                    }, {
                        cmdName: "cellalignment",
                        value: {
                            align: "center",
                            vAlign: "bottom"
                        }
                    }, {
                        cmdName: "cellalignment",
                        value: {
                            align: "right",
                            vAlign: "bottom"
                        }
                    }]
                }, {
                    group: lang.aligntable,
                    icon: "aligntable",
                    subMenu: [{
                        cmdName: "tablealignment",
                        className: "left",
                        label: lang.tableleft,
                        value: "left"
                    }, {
                        cmdName: "tablealignment",
                        className: "center",
                        label: lang.tablecenter,
                        value: "center"
                    }, {
                        cmdName: "tablealignment",
                        className: "right",
                        label: lang.tableright,
                        value: "right"
                    }]
                }, "-",
                {
                    label: lang.insertparagraphbefore,
                    cmdName: "insertparagraph",
                    value: true
                }, {
                    label: lang.insertparagraphafter,
                    cmdName: "insertparagraph"
                }, {
                    label: lang["copy"],
                    cmdName: "copy"
                }, {
                    label: lang["paste"],
                    cmdName: "paste"
                }];
        if (!items.length) {
            return
        }
        var uiUtils = UE.ui.uiUtils;
        me.addListener("contextmenu", function(type, evt) {
            var offset = uiUtils.getViewportOffsetByEvent(evt);
            me.fireEvent("beforeselectionchange");
            if (menu) {
                menu.destroy()
            }
            for (var i = 0, ti, contextItems = []; ti = items[i]; i++) {
                var last;
                (function(item) {
                    if (item == "-") {
                        if ((last = contextItems[contextItems.length - 1]) && last !== "-") {
                            contextItems.push("-")
                        }
                    } else {
                        if (item.hasOwnProperty("group")) {
                            for (var j = 0, cj, subMenu = []; cj = item.subMenu[j]; j++) {
                                (function(subItem) {
                                    if (subItem == "-") {
                                        if ((last = subMenu[subMenu.length - 1]) && last !== "-") {
                                            subMenu.push("-")
                                        } else {
                                            subMenu.splice(subMenu.length - 1)
                                        }
                                    } else {
                                        if ((me.commands[subItem.cmdName] || UE.commands[subItem.cmdName] || subItem.query) && (subItem.query ? subItem.query() : me.queryCommandState(subItem.cmdName)) > -1) {
                                            subMenu.push({
                                                "label": subItem.label || me.getLang("contextMenu." + subItem.cmdName + (subItem.value || "")) || "",
                                                "className": "edui-for-" + subItem.cmdName + (subItem.className ? (" edui-for-" + subItem.cmdName + "-" + subItem.className) : ""),
                                                onclick: subItem.exec ?
                                                    function() {
                                                        subItem.exec.call(me)
                                                    } : function() {
                                                        me.execCommand(subItem.cmdName, subItem.value)
                                                    }
                                            })
                                        }
                                    }
                                })(cj)
                            }
                            if (subMenu.length) {
                                function getLabel() {
                                    switch (item.icon) {
                                        case "table":
                                            return me.getLang("contextMenu.table");
                                        case "justifyjustify":
                                            return me.getLang("contextMenu.paragraph");
                                        case "aligntd":
                                            return me.getLang("contextMenu.aligntd");
                                        case "aligntable":
                                            return me.getLang("contextMenu.aligntable");
                                        case "tablesort":
                                            return lang.tablesort;
                                        case "borderBack":
                                            return lang.borderbk;
                                        default:
                                            return ""
                                    }
                                }
                                contextItems.push({
                                    "label": getLabel(),
                                    className: "edui-for-" + item.icon,
                                    "subMenu": {
                                        items: subMenu,
                                        editor: me
                                    }
                                })
                            }
                        } else {
                            if ((me.commands[item.cmdName] || UE.commands[item.cmdName] || item.query) && (item.query ? item.query.call(me) : me.queryCommandState(item.cmdName)) > -1) {
                                contextItems.push({
                                    "label": item.label || me.getLang("contextMenu." + item.cmdName),
                                    className: "edui-for-" + (item.icon ? item.icon : item.cmdName + (item.value || "")),
                                    onclick: item.exec ?
                                        function() {
                                            item.exec.call(me)
                                        } : function() {
                                            me.execCommand(item.cmdName, item.value)
                                        }
                                })
                            }
                        }
                    }
                })(ti)
            }
            if (contextItems[contextItems.length - 1] == "-") {
                contextItems.pop()
            }
            menu = new UE.ui.Menu({
                items: contextItems,
                className: "edui-contextmenu",
                editor: me
            });
            menu.render();
            menu.showAt(offset);
            me.fireEvent("aftershowcontextmenu", menu);
            domUtils.preventDefault(evt);
            if (browser.ie) {
                var ieRange;
                try {
                    ieRange = me.selection.getNative().createRange()
                } catch (e) {
                    return
                }
                if (ieRange.item) {
                    var range = new dom.Range(me.document);
                    range.selectNode(ieRange.item(0)).select(true, true)
                }
            }
        });
        me.addListener("aftershowcontextmenu", function(type, menu) {
            if (me.zeroclipboard) {
                var items = menu.items;
                for (var key in items) {
                    if (items[key].className == "edui-for-copy") {
                        me.zeroclipboard.clip(items[key].getDom())
                    }
                }
            }
        })
    };
    UE.plugins["shortcutmenu"] = function() {
        var me = this,
            menu, items = me.options.shortcutMenu || [];
        if (!items.length) {
            return
        }
        me.addListener("contextmenu mouseup", function(type, e) {
            var me = this,
                customEvt = {
                    type: type,
                    target: e.target || e.srcElement,
                    screenX: e.screenX,
                    screenY: e.screenY,
                    clientX: e.clientX,
                    clientY: e.clientY
                };
            setTimeout(function() {
                var rng = me.selection.getRange();
                if (rng.collapsed === false || type == "contextmenu") {
                    if (!menu) {
                        menu = new baidu.editor.ui.ShortCutMenu({
                            editor: me,
                            items: items,
                            theme: me.options.theme,
                            className: "edui-shortcutmenu"
                        });
                        menu.render();
                        me.fireEvent("afterrendershortcutmenu", menu)
                    }
                    menu.show(customEvt, !! UE.plugins["contextmenu"])
                }
            });
            if (type == "contextmenu") {
                domUtils.preventDefault(e);
                if (browser.ie9below) {
                    var ieRange;
                    try {
                        ieRange = me.selection.getNative().createRange()
                    } catch (e) {
                        return
                    }
                    if (ieRange.item) {
                        var range = new dom.Range(me.document);
                        range.selectNode(ieRange.item(0)).select(true, true)
                    }
                }
            }
        });
        me.addListener("keydown", function(type) {
            if (type == "keydown") {
                menu && !menu.isHidden && menu.hide()
            }
        })
    };
    UE.plugins["basestyle"] = function() {
        var basestyles = {
                "bold": ["strong", "b"],
                "italic": ["em", "i"],
                "subscript": ["sub"],
                "superscript": ["sup"]
            },
            getObj = function(editor, tagNames) {
                return domUtils.filterNodeList(editor.selection.getStartElementPath(), tagNames)
            },
            me = this;
        me.addshortcutkey({
            "Bold": "ctrl+66",
            "Italic": "ctrl+73",
            "Underline": "ctrl+85"
        });
        me.addInputRule(function(root) {
            utils.each(root.getNodesByTagName("b i"), function(node) {
                switch (node.tagName) {
                    case "b":
                        node.tagName = "strong";
                        break;
                    case "i":
                        node.tagName = "em"
                }
            })
        });
        for (var style in basestyles) {
            (function(cmd, tagNames) {
                me.commands[cmd] = {
                    execCommand: function(cmdName) {
                        var range = me.selection.getRange(),
                            obj = getObj(this, tagNames);
                        if (range.collapsed) {
                            if (obj) {
                                var tmpText = me.document.createTextNode("");
                                range.insertNode(tmpText).removeInlineStyle(tagNames);
                                range.setStartBefore(tmpText);
                                domUtils.remove(tmpText)
                            } else {
                                var tmpNode = range.document.createElement(tagNames[0]);
                                if (cmdName == "superscript" || cmdName == "subscript") {
                                    tmpText = me.document.createTextNode("");
                                    range.insertNode(tmpText).removeInlineStyle(["sub", "sup"]).setStartBefore(tmpText).collapse(true)
                                }
                                range.insertNode(tmpNode).setStart(tmpNode, 0)
                            }
                            range.collapse(true)
                        } else {
                            if (cmdName == "superscript" || cmdName == "subscript") {
                                if (!obj || obj.tagName.toLowerCase() != cmdName) {
                                    range.removeInlineStyle(["sub", "sup"])
                                }
                            }
                            obj ? range.removeInlineStyle(tagNames) : range.applyInlineStyle(tagNames[0])
                        }
                        range.select()
                    },
                    queryCommandState: function() {
                        return getObj(this, tagNames) ? 1 : 0
                    }
                }
            })(style, basestyles[style])
        }
    };
    UE.plugins["elementpath"] = function() {
        var currentLevel, tagNames, me = this;
        me.setOpt("elementPathEnabled", true);
        if (!me.options.elementPathEnabled) {
            return
        }
        me.commands["elementpath"] = {
            execCommand: function(cmdName, level) {
                var start = tagNames[level],
                    range = me.selection.getRange();
                currentLevel = level * 1;
                range.selectNode(start).select()
            },
            queryCommandValue: function() {
                var parents = [].concat(this.selection.getStartElementPath()).reverse(),
                    names = [];
                tagNames = parents;
                for (var i = 0, ci; ci = parents[i]; i++) {
                    if (ci.nodeType == 3) {
                        continue
                    }
                    var name = ci.tagName.toLowerCase();
                    if (name == "img" && ci.getAttribute("anchorname")) {
                        name = "anchor"
                    }
                    names[i] = name;
                    if (currentLevel == i) {
                        currentLevel = -1;
                        break
                    }
                }
                return names
            }
        }
    };
    UE.plugins["formatmatch"] = function() {
        var me = this,
            list = [],
            img, flag = 0;
        me.addListener("reset", function() {
            list = [];
            flag = 0
        });

        function addList(type, evt) {
            if (browser.webkit) {
                var target = evt.target.tagName == "IMG" ? evt.target : null
            }
            function addFormat(range) {
                if (text) {
                    range.selectNode(text)
                }
                return range.applyInlineStyle(list[list.length - 1].tagName, null, list)
            }
            me.undoManger && me.undoManger.save();
            var range = me.selection.getRange(),
                imgT = target || range.getClosedNode();
            if (img && imgT && imgT.tagName == "IMG") {
                imgT.style.cssText += ";float:" + (img.style.cssFloat || img.style.styleFloat || "none") + ";display:" + (img.style.display || "inline");
                img = null
            } else {
                if (!img) {
                    var collapsed = range.collapsed;
                    if (collapsed) {
                        var text = me.document.createTextNode("match");
                        range.insertNode(text).select()
                    }
                    me.__hasEnterExecCommand = true;
                    var removeFormatAttributes = me.options.removeFormatAttributes;
                    me.options.removeFormatAttributes = "";
                    me.execCommand("removeformat");
                    me.options.removeFormatAttributes = removeFormatAttributes;
                    me.__hasEnterExecCommand = false;
                    range = me.selection.getRange();
                    if (list.length) {
                        addFormat(range)
                    }
                    if (text) {
                        range.setStartBefore(text).collapse(true)
                    }
                    range.select();
                    text && domUtils.remove(text)
                }
            }
            me.undoManger && me.undoManger.save();
            me.removeListener("mouseup", addList);
            flag = 0
        }
        me.commands["formatmatch"] = {
            execCommand: function(cmdName) {
                if (flag) {
                    flag = 0;
                    list = [];
                    me.removeListener("mouseup", addList);
                    return
                }
                var range = me.selection.getRange();
                img = range.getClosedNode();
                if (!img || img.tagName != "IMG") {
                    range.collapse(true).shrinkBoundary();
                    var start = range.startContainer;
                    list = domUtils.findParents(start, true, function(node) {
                        return !domUtils.isBlockElm(node) && node.nodeType == 1
                    });
                    for (var i = 0, ci; ci = list[i]; i++) {
                        if (ci.tagName == "A") {
                            list.splice(i, 1);
                            break
                        }
                    }
                }
                me.addListener("mouseup", addList);
                flag = 1
            },
            queryCommandState: function() {
                return flag
            },
            notNeedUndo: 1
        }
    };
    UE.plugin.register("searchreplace", function() {
        var me = this;
        var _blockElm = {
            "table": 1,
            "tbody": 1,
            "tr": 1,
            "ol": 1,
            "ul": 1
        };

        function findTextInString(textContent, opt, currentIndex) {
            var str = opt.searchStr;
            if (opt.dir == -1) {
                textContent = textContent.split("").reverse().join("");
                str = str.split("").reverse().join("");
                currentIndex = textContent.length - currentIndex
            }
            var reg = new RegExp(str, "g" + (opt.casesensitive ? "" : "i")),
                match;
            while (match = reg.exec(textContent)) {
                if (match.index >= currentIndex) {
                    return opt.dir == -1 ? textContent.length - match.index - opt.searchStr.length : match.index
                }
            }
            return -1
        }
        function findTextBlockElm(node, currentIndex, opt) {
            var textContent, index, methodName = opt.all || opt.dir == 1 ? "getNextDomNode" : "getPreDomNode";
            if (domUtils.isBody(node)) {
                node = node.firstChild
            }
            var first = 1;
            while (node) {
                textContent = node.nodeType == 3 ? node.nodeValue : node[browser.ie ? "innerText" : "textContent"];
                index = findTextInString(textContent, opt, currentIndex);
                first = 0;
                if (index != -1) {
                    return {
                        "node": node,
                        "index": index
                    }
                }
                node = domUtils[methodName](node);
                while (node && _blockElm[node.nodeName.toLowerCase()]) {
                    node = domUtils[methodName](node, true)
                }
                if (node) {
                    currentIndex = opt.dir == -1 ? (node.nodeType == 3 ? node.nodeValue : node[browser.ie ? "innerText" : "textContent"]).length : 0
                }
            }
        }
        function findNTextInBlockElm(node, index, str) {
            var currentIndex = 0,
                currentNode = node.firstChild,
                currentNodeLength = 0,
                result;
            while (currentNode) {
                if (currentNode.nodeType == 3) {
                    currentNodeLength = currentNode.nodeValue.replace(/(^[\t\r\n]+)|([\t\r\n]+$)/, "").length;
                    currentIndex += currentNodeLength;
                    if (currentIndex >= index) {
                        return {
                            "node": currentNode,
                            "index": currentNodeLength - (currentIndex - index)
                        }
                    }
                } else {
                    if (!dtd.$empty[currentNode.tagName]) {
                        currentNodeLength = currentNode[browser.ie ? "innerText" : "textContent"].replace(/(^[\t\r\n]+)|([\t\r\n]+$)/, "").length;
                        currentIndex += currentNodeLength;
                        if (currentIndex >= index) {
                            result = findNTextInBlockElm(currentNode, currentNodeLength - (currentIndex - index), str);
                            if (result) {
                                return result
                            }
                        }
                    }
                }
                currentNode = domUtils.getNextDomNode(currentNode)
            }
        }
        function searchReplace(me, opt) {
            var rng = me.selection.getRange(),
                startBlockNode, searchStr = opt.searchStr,
                span = me.document.createElement("span");
            span.innerHTML = "$$ueditor_searchreplace_key$$";
            rng.shrinkBoundary(true);
            if (!rng.collapsed) {
                rng.select();
                var rngText = me.selection.getText();
                if (new RegExp("^" + opt.searchStr + "$", (opt.casesensitive ? "" : "i")).test(rngText)) {
                    if (opt.replaceStr != undefined) {
                        replaceText(rng, opt.replaceStr);
                        rng.select();
                        return true
                    } else {
                        rng.collapse(opt.dir == -1)
                    }
                }
            }
            rng.insertNode(span);
            rng.enlargeToBlockElm(true);
            startBlockNode = rng.startContainer;
            var currentIndex = startBlockNode[browser.ie ? "innerText" : "textContent"].indexOf("$$ueditor_searchreplace_key$$");
            rng.setStartBefore(span);
            domUtils.remove(span);
            var result = findTextBlockElm(startBlockNode, currentIndex, opt);
            if (result) {
                var rngStart = findNTextInBlockElm(result.node, result.index, searchStr);
                var rngEnd = findNTextInBlockElm(result.node, result.index + searchStr.length, searchStr);
                rng.setStart(rngStart.node, rngStart.index).setEnd(rngEnd.node, rngEnd.index);
                if (opt.replaceStr !== undefined) {
                    replaceText(rng, opt.replaceStr)
                }
                rng.select();
                return true
            } else {
                rng.setCursor()
            }
        }
        function replaceText(rng, str) {
            str = me.document.createTextNode(str);
            rng.deleteContents().insertNode(str)
        }
        return {
            commands: {
                "searchreplace": {
                    execCommand: function(cmdName, opt) {
                        utils.extend(opt, {
                            all: false,
                            casesensitive: false,
                            dir: 1
                        }, true);
                        var num = 0;
                        if (opt.all) {
                            var rng = me.selection.getRange(),
                                first = me.body.firstChild;
                            if (first && first.nodeType == 1) {
                                rng.setStart(first, 0);
                                rng.shrinkBoundary(true)
                            } else {
                                if (first.nodeType == 3) {
                                    rng.setStartBefore(first)
                                }
                            }
                            rng.collapse(true).select(true);
                            if (opt.replaceStr !== undefined) {
                                me.fireEvent("saveScene")
                            }
                            while (searchReplace(this, opt)) {
                                num++
                            }
                            if (num) {
                                me.fireEvent("saveScene")
                            }
                        } else {
                            if (opt.replaceStr !== undefined) {
                                me.fireEvent("saveScene")
                            }
                            if (searchReplace(this, opt)) {
                                num++
                            }
                            if (num) {
                                me.fireEvent("saveScene")
                            }
                        }
                        return num
                    },
                    notNeedUndo: 1
                }
            }
        }
    });
    UE.plugins["customstyle"] = function() {
        var me = this;
        me.setOpt({
            "customstyle": [{
                tag: "h1",
                name: "tc",
                style: "font-size:32px;font-weight:bold;border-bottom:#ccc 2px solid;padding:0 4px 0 0;text-align:center;margin:0 0 20px 0;"
            }, {
                tag: "h1",
                name: "tl",
                style: "font-size:32px;font-weight:bold;border-bottom:#ccc 2px solid;padding:0 4px 0 0;text-align:left;margin:0 0 10px 0;"
            }, {
                tag: "span",
                name: "im",
                style: "font-size:16px;font-style:italic;font-weight:bold;line-height:18px;"
            }, {
                tag: "span",
                name: "hi",
                style: "font-size:16px;font-style:italic;font-weight:bold;color:rgb(51, 153, 204);line-height:18px;"
            }]
        });
        me.commands["customstyle"] = {
            execCommand: function(cmdName, obj) {
                var me = this,
                    tagName = obj.tag,
                    node = domUtils.findParent(me.selection.getStart(), function(node) {
                        return node.getAttribute("label")
                    }, true),
                    range, bk, tmpObj = {};
                for (var p in obj) {
                    if (obj[p] !== undefined) {
                        tmpObj[p] = obj[p]
                    }
                }
                delete tmpObj.tag;
                if (node && node.getAttribute("label") == obj.label) {
                    range = this.selection.getRange();
                    bk = range.createBookmark();
                    if (range.collapsed) {
                        if (dtd.$block[node.tagName]) {
                            var fillNode = me.document.createElement("p");
                            domUtils.moveChild(node, fillNode);
                            node.parentNode.insertBefore(fillNode, node);
                            domUtils.remove(node)
                        } else {
                            domUtils.remove(node, true)
                        }
                    } else {
                        var common = domUtils.getCommonAncestor(bk.start, bk.end),
                            nodes = domUtils.getElementsByTagName(common, tagName);
                        if (new RegExp(tagName, "i").test(common.tagName)) {
                            nodes.push(common)
                        }
                        for (var i = 0, ni; ni = nodes[i++];) {
                            if (ni.getAttribute("label") == obj.label) {
                                var ps = domUtils.getPosition(ni, bk.start),
                                    pe = domUtils.getPosition(ni, bk.end);
                                if ((ps & domUtils.POSITION_FOLLOWING || ps & domUtils.POSITION_CONTAINS) && (pe & domUtils.POSITION_PRECEDING || pe & domUtils.POSITION_CONTAINS)) {
                                    if (dtd.$block[tagName]) {
                                        var fillNode = me.document.createElement("p");
                                        domUtils.moveChild(ni, fillNode);
                                        ni.parentNode.insertBefore(fillNode, ni)
                                    }
                                }
                                domUtils.remove(ni, true)
                            }
                        }
                        node = domUtils.findParent(common, function(node) {
                            return node.getAttribute("label") == obj.label
                        }, true);
                        if (node) {
                            domUtils.remove(node, true)
                        }
                    }
                    range.moveToBookmark(bk).select()
                } else {
                    if (dtd.$block[tagName]) {
                        this.execCommand("paragraph", tagName, tmpObj, "customstyle");
                        range = me.selection.getRange();
                        if (!range.collapsed) {
                            range.collapse();
                            node = domUtils.findParent(me.selection.getStart(), function(node) {
                                return node.getAttribute("label") == obj.label
                            }, true);
                            var pNode = me.document.createElement("p");
                            domUtils.insertAfter(node, pNode);
                            domUtils.fillNode(me.document, pNode);
                            range.setStart(pNode, 0).setCursor()
                        }
                    } else {
                        range = me.selection.getRange();
                        if (range.collapsed) {
                            node = me.document.createElement(tagName);
                            domUtils.setAttributes(node, tmpObj);
                            range.insertNode(node).setStart(node, 0).setCursor();
                            return
                        }
                        bk = range.createBookmark();
                        range.applyInlineStyle(tagName, tmpObj).moveToBookmark(bk).select()
                    }
                }
            },
            queryCommandValue: function() {
                var parent = domUtils.filterNodeList(this.selection.getStartElementPath(), function(node) {
                    return node.getAttribute("label")
                });
                return parent ? parent.getAttribute("label") : ""
            }
        };
        me.addListener("keyup", function(type, evt) {
            var keyCode = evt.keyCode || evt.which;
            if (keyCode == 32 || keyCode == 13) {
                var range = me.selection.getRange();
                if (range.collapsed) {
                    var node = domUtils.findParent(me.selection.getStart(), function(node) {
                        return node.getAttribute("label")
                    }, true);
                    if (node && dtd.$block[node.tagName] && domUtils.isEmptyNode(node)) {
                        var p = me.document.createElement("p");
                        domUtils.insertAfter(node, p);
                        domUtils.fillNode(me.document, p);
                        domUtils.remove(node);
                        range.setStart(p, 0).setCursor()
                    }
                }
            }
        })
    };
    UE.plugins["catchremoteimage"] = function() {
        var me = this,
            ajax = UE.ajax;
        if (me.options.catchRemoteImageEnable === false) {
            return
        }
        me.setOpt({
            catchRemoteImageEnable: false
        });
        me.addListener("afterpaste", function() {
            me.fireEvent("catchRemoteImage")
        });
        me.addListener("catchRemoteImage", function() {
            var catcherLocalDomain = me.getOpt("catcherLocalDomain"),
                catcherActionUrl = me.getActionUrl(me.getOpt("catcherActionName")),
                catcherUrlPrefix = me.getOpt("catcherUrlPrefix"),
                catcherFieldName = me.getOpt("catcherFieldName");
            var remoteImages = [],
                imgs = domUtils.getElementsByTagName(me.document, "img"),
                test = function(src, urls) {
                    if (src.indexOf(location.host) != -1 || /(^\.)|(^\/)/.test(src)) {
                        return true
                    }
                    if (urls) {
                        for (var j = 0, url; url = urls[j++];) {
                            if (src.indexOf(url) !== -1) {
                                return true
                            }
                        }
                    }
                    return false
                };
            for (var i = 0, ci; ci = imgs[i++];) {
                if (ci.getAttribute("word_img")) {
                    continue
                }
                var src = ci.getAttribute("_src") || ci.src || "";
                if (/^(https?|ftp):/i.test(src) && !test(src, catcherLocalDomain)) {
                    remoteImages.push(src)
                }
            }
            if (remoteImages.length) {
                catchremoteimage(remoteImages, {
                    success: function(r) {
                        try {
                            var info = r.state !== undefined ? r : eval("(" + r.responseText + ")")
                        } catch (e) {
                            return
                        }
                        var i, j, ci, cj, oldSrc, newSrc, list = info.list;
                        for (i = 0; ci = imgs[i++];) {
                            oldSrc = ci.getAttribute("_src") || ci.src || "";
                            for (j = 0; cj = list[j++];) {
                                if (oldSrc == cj.source && cj.state == "SUCCESS") {
                                    newSrc = catcherUrlPrefix + cj.url;
                                    domUtils.setAttributes(ci, {
                                        "src": newSrc,
                                        "_src": newSrc
                                    });
                                    break
                                }
                            }
                        }
                        me.fireEvent("catchremotesuccess")
                    },
                    error: function() {
                        me.fireEvent("catchremoteerror")
                    }
                })
            }
            function catchremoteimage(imgs, callbacks) {
                var params = utils.serializeParam(me.queryCommandValue("serverparam")) || "",
                    url = utils.formatUrl(catcherActionUrl + (catcherActionUrl.indexOf("?") == -1 ? "?" : "&") + params),
                    isJsonp = utils.isCrossDomainUrl(url),
                    opt = {
                        "method": "POST",
                        "dataType": isJsonp ? "jsonp" : "",
                        "timeout": 60000,
                        "onsuccess": callbacks["success"],
                        "onerror": callbacks["error"]
                    };
                opt[catcherFieldName] = imgs;
                ajax.request(url, opt)
            }
        })
    };
    UE.plugin.register("snapscreen", function() {
        var me = this;
        var snapplugin;

        function getLocation(url) {
            var search, a = document.createElement("a"),
                params = utils.serializeParam(me.queryCommandValue("serverparam")) || "";
            a.href = url;
            if (browser.ie) {
                a.href = a.href
            }
            search = a.search;
            if (params) {
                search = search + (search.indexOf("?") == -1 ? "?" : "&") + params;
                search = search.replace(/[&]+/ig, "&")
            }
            return {
                "port": a.port,
                "hostname": a.hostname,
                "path": a.pathname + search || +a.hash
            }
        }
        return {
            commands: {
                "snapscreen": {
                    execCommand: function(cmd) {
                        var url, local, res;
                        var lang = me.getLang("snapScreen_plugin");
                        if (!snapplugin) {
                            var container = me.container;
                            var doc = me.container.ownerDocument || me.container.document;
                            snapplugin = doc.createElement("object");
                            try {
                                snapplugin.type = "application/x-pluginbaidusnap"
                            } catch (e) {
                                return
                            }
                            snapplugin.style.cssText = "position:absolute;left:-9999px;width:0;height:0;";
                            snapplugin.setAttribute("width", "0");
                            snapplugin.setAttribute("height", "0");
                            container.appendChild(snapplugin)
                        }
                        function onSuccess(rs) {
                            try {
                                rs = eval("(" + rs + ")");
                                if (rs.state == "SUCCESS") {
                                    var opt = me.options;
                                    me.execCommand("insertimage", {
                                        src: opt.snapscreenUrlPrefix + rs.url,
                                        _src: opt.snapscreenUrlPrefix + rs.url,
                                        alt: rs.title || "",
                                        floatStyle: opt.snapscreenImgAlign
                                    })
                                } else {
                                    alert(rs.state)
                                }
                            } catch (e) {
                                alert(lang.callBackErrorMsg)
                            }
                        }
                        url = me.getActionUrl(me.getOpt("snapscreenActionName"));
                        local = getLocation(url);
                        setTimeout(function() {
                            try {
                                res = snapplugin.saveSnapshot(local.hostname, local.path, local.port)
                            } catch (e) {
                                me.ui._dialogs["snapscreenDialog"].open();
                                return
                            }
                            onSuccess(res)
                        }, 50)
                    },
                    queryCommandState: function() {
                        return (navigator.userAgent.indexOf("Windows", 0) != -1) ? 0 : -1
                    }
                }
            }
        }
    });
    UE.commands["insertparagraph"] = {
        execCommand: function(cmdName, front) {
            var me = this,
                range = me.selection.getRange(),
                start = range.startContainer,
                tmpNode;
            while (start) {
                if (domUtils.isBody(start)) {
                    break
                }
                tmpNode = start;
                start = start.parentNode
            }
            if (tmpNode) {
                var p = me.document.createElement("p");
                if (front) {
                    tmpNode.parentNode.insertBefore(p, tmpNode)
                } else {
                    tmpNode.parentNode.insertBefore(p, tmpNode.nextSibling)
                }
                domUtils.fillNode(me.document, p);
                range.setStart(p, 0).setCursor(false, true)
            }
        }
    };
    UE.plugin.register("webapp", function() {
        var me = this;

        function createInsertStr(obj, toEmbed) {
            return !toEmbed ? '<img title="' + obj.title + '" width="' + obj.width + '" height="' + obj.height + '"' + ' src="' + me.options.UEDITOR_HOME_URL + 'themes/default/images/spacer.gif" _logo_url="' + obj.logo + '" style="background:url(' + obj.logo + ') no-repeat center center; border:1px solid gray;" class="edui-faked-webapp" _url="' + obj.url + '" ' + (obj.align && !obj.cssfloat ? 'align="' + obj.align + '"' : "") + (obj.cssfloat ? 'style="float:' + obj.cssfloat + '"' : "") + "/>" : '<iframe class="edui-faked-webapp" title="' + obj.title + '" ' + (obj.align && !obj.cssfloat ? 'align="' + obj.align + '"' : "") + (obj.cssfloat ? 'style="float:' + obj.cssfloat + '"' : "") + 'width="' + obj.width + '" height="' + obj.height + '"  scrolling="no" frameborder="0" src="' + obj.url + '" logo_url = "' + obj.logo + '"></iframe>'
        }
        return {
            outputRule: function(root) {
                utils.each(root.getNodesByTagName("img"), function(node) {
                    var html;
                    if (node.getAttr("class") == "edui-faked-webapp") {
                        html = createInsertStr({
                            title: node.getAttr("title"),
                            "width": node.getAttr("width"),
                            "height": node.getAttr("height"),
                            "align": node.getAttr("align"),
                            "cssfloat": node.getStyle("float"),
                            "url": node.getAttr("_url"),
                            "logo": node.getAttr("_logo_url")
                        }, true);
                        var embed = UE.uNode.createElement(html);
                        node.parentNode.replaceChild(embed, node)
                    }
                })
            },
            inputRule: function(root) {
                utils.each(root.getNodesByTagName("iframe"), function(node) {
                    if (node.getAttr("class") == "edui-faked-webapp") {
                        var img = UE.uNode.createElement(createInsertStr({
                            title: node.getAttr("title"),
                            "width": node.getAttr("width"),
                            "height": node.getAttr("height"),
                            "align": node.getAttr("align"),
                            "cssfloat": node.getStyle("float"),
                            "url": node.getAttr("src"),
                            "logo": node.getAttr("logo_url")
                        }));
                        node.parentNode.replaceChild(img, node)
                    }
                })
            },
            commands: {
                "webapp": {
                    execCommand: function(cmd, obj) {
                        var me = this,
                            str = createInsertStr(utils.extend(obj, {
                                align: "none"
                            }), false);
                        me.execCommand("inserthtml", str)
                    },
                    queryCommandState: function() {
                        var me = this,
                            img = me.selection.getRange().getClosedNode(),
                            flag = img && (img.className == "edui-faked-webapp");
                        return flag ? 1 : 0
                    }
                }
            }
        }
    });
    UE.plugins["template"] = function() {
        UE.commands["template"] = {
            execCommand: function(cmd, obj) {
                obj.html && this.execCommand("inserthtml", obj.html)
            }
        };
        this.addListener("click", function(type, evt) {
            var el = evt.target || evt.srcElement,
                range = this.selection.getRange();
            var tnode = domUtils.findParent(el, function(node) {
                if (node.className && domUtils.hasClass(node, "ue_t")) {
                    return node
                }
            }, true);
            tnode && range.selectNode(tnode).shrinkBoundary().select()
        });
        this.addListener("keydown", function(type, evt) {
            var range = this.selection.getRange();
            if (!range.collapsed) {
                if (!evt.ctrlKey && !evt.metaKey && !evt.shiftKey && !evt.altKey) {
                    var tnode = domUtils.findParent(range.startContainer, function(node) {
                        if (node.className && domUtils.hasClass(node, "ue_t")) {
                            return node
                        }
                    }, true);
                    if (tnode) {
                        domUtils.removeClasses(tnode, ["ue_t"])
                    }
                }
            }
        })
    };
    UE.plugin.register("music", function() {
        var me = this;
        function creatInsertStr(url, width, height, align, cssfloat, toEmbed) {
            return !toEmbed ? "<img " + (align && !cssfloat ? 'align="' + align + '"' : "") + (cssfloat ? 'style="float:' + cssfloat + '"' : "") + ' width="' + width + '" height="' + height + '" _url="' + url + '" class="edui-faked-music"' + ' src="' + me.options.langPath + me.options.lang + '/images/music.png" />'
                : '<embed type="application/x-shockwave-flash" class="edui-faked-music" pluginspage="http://www.macromedia.com/go/getflashplayer"' + ' src="' + url + '" width="' + width + '" height="' + height + '" ' + (align && !cssfloat ? 'align="' + align + '"' : "") + (cssfloat ? 'style="float:' + cssfloat + '"' : "") + ' wmode="transparent" play="true" loop="false" menu="false" allowscriptaccess="never" allowfullscreen="true" >'
        }
        return {
            outputRule: function(root) {
                utils.each(root.getNodesByTagName("img"), function(node) {
                    var html;
                    if (node.getAttr("class") == "edui-faked-music") {
                        var cssfloat = node.getStyle("float");
                        var align = node.getAttr("align");
                        html = creatInsertStr(node.getAttr("_url"), node.getAttr("width"), node.getAttr("height"), align, cssfloat, true);
                        var embed = UE.uNode.createElement(html);
                        node.parentNode.replaceChild(embed, node)
                    }
                })
            },
            inputRule: function(root) {
                utils.each(root.getNodesByTagName("embed"), function(node) {
                    if (node.getAttr("class") == "edui-faked-music") {
                        var cssfloat = node.getStyle("float");
                        var align = node.getAttr("align");
                        html = creatInsertStr(node.getAttr("src"), node.getAttr("width"), node.getAttr("height"), align, cssfloat, false);
                        var img = UE.uNode.createElement(html);
                        node.parentNode.replaceChild(img, node)
                    }
                })
            },
            commands: {
                "music": {
                    execCommand: function(cmd, musicObj) {
                        var me = this,
                            str = creatInsertStr(musicObj.url, musicObj.width || 400, musicObj.height || 95, "none", false);
                        me.execCommand("inserthtml", str)
                    },
                    queryCommandState: function() {
                        var me = this,
                            img = me.selection.getRange().getClosedNode(),
                            flag = img && (img.className == "edui-faked-music");
                        return flag ? 1 : 0
                    }
                }
            }
        }
    });
    UE.plugin.register("autoupload", function() {
        function sendAndInsertFile(file, editor) {
            var me = editor;
            var fieldName, urlPrefix, maxSize, allowFiles, actionUrl, loadingHtml, errorHandler, successHandler, filetype = /image\/\w+/i.test(file.type) ? "image" : "file",
                loadingId = "loading_" + (+new Date()).toString(36);
            fieldName = me.getOpt(filetype + "FieldName");
            urlPrefix = me.getOpt(filetype + "UrlPrefix");
            maxSize = me.getOpt(filetype + "MaxSize");
            allowFiles = me.getOpt(filetype + "AllowFiles");
            actionUrl = me.getActionUrl(me.getOpt(filetype + "ActionName"));
            errorHandler = function(title) {
                var loader = me.document.getElementById(loadingId);
                loader && domUtils.remove(loader);
                me.fireEvent("showmessage", {
                    "id": loadingId,
                    "content": title,
                    "type": "error",
                    "timeout": 4000
                })
            };
            if (filetype == "image") {
                loadingHtml = '<img class="loadingclass" id="' + loadingId + '" src="' + me.options.themePath + me.options.theme + '/images/spacer.gif" title="' + (me.getLang("autoupload.loading") || "") + '" >';
                successHandler = function(data) {
                    var link = urlPrefix + data.url,
                        loader = me.document.getElementById(loadingId);
                    if (loader) {
                        loader.setAttribute("src", link);
                        loader.setAttribute("_src", link);
                        loader.setAttribute("title", data.title || "");
                        loader.setAttribute("alt", data.original || "");
                        loader.removeAttribute("id");
                        domUtils.removeClasses(loader, "loadingclass")
                    }
                }
            } else {
                loadingHtml = "<p>" + '<img class="loadingclass" id="' + loadingId + '" src="' + me.options.themePath + me.options.theme + '/images/spacer.gif" title="' + (me.getLang("autoupload.loading") || "") + '" >' + "</p>";
                successHandler = function(data) {
                    var link = urlPrefix + data.url,
                        loader = me.document.getElementById(loadingId);
                    var rng = me.selection.getRange(),
                        bk = rng.createBookmark();
                    rng.selectNode(loader).select();
                    me.execCommand("insertfile", {
                        "url": link
                    });
                    rng.moveToBookmark(bk).select()
                }
            }
            me.execCommand("inserthtml", loadingHtml);
            if (!me.getOpt(filetype + "ActionName")) {
                errorHandler(me.getLang("autoupload.errorLoadConfig"));
                return
            }
            if (file.size > maxSize) {
                errorHandler(me.getLang("autoupload.exceedSizeError"));
                return
            }
            var fileext = file.name ? file.name.substr(file.name.lastIndexOf(".")) : "";
            if ((fileext && filetype != "image") || (allowFiles && (allowFiles.join("") + ".").indexOf(fileext.toLowerCase() + ".") == -1)) {
                errorHandler(me.getLang("autoupload.exceedTypeError"));
                return
            }
            var xhr = new XMLHttpRequest(),
                fd = new FormData(),
                params = utils.serializeParam(me.queryCommandValue("serverparam")) || "",
                url = utils.formatUrl(actionUrl + (actionUrl.indexOf("?") == -1 ? "?" : "&") + params);
            alert(url);
            fd.append(fieldName, file, file.name || ("blob." + file.type.substr("image/".length)));
            fd.append("type", "ajax");
            xhr.open("post", url, true);
            xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
            xhr.addEventListener("load", function(e) {
                try {
                    var json = (new Function("return " + utils.trim(e.target.response)))();
                    if (json.state == "SUCCESS" && json.url) {
                        successHandler(json)
                    } else {
                        errorHandler(json.state)
                    }
                } catch (er) {
                    errorHandler(me.getLang("autoupload.loadError"))
                }
            });
            xhr.send(fd)
        }
        function getPasteImage(e) {
            return e.clipboardData && e.clipboardData.items && e.clipboardData.items.length == 1 && /^image\//.test(e.clipboardData.items[0].type) ? e.clipboardData.items : null
        }
        function getDropImage(e) {
            return e.dataTransfer && e.dataTransfer.files ? e.dataTransfer.files : null
        }
        return {
            outputRule: function(root) {
                utils.each(root.getNodesByTagName("img"), function(n) {
                    if (/\b(loaderrorclass)|(bloaderrorclass)\b/.test(n.getAttr("class"))) {
                        n.parentNode.removeChild(n)
                    }
                });
                utils.each(root.getNodesByTagName("p"), function(n) {
                    if (/\bloadpara\b/.test(n.getAttr("class"))) {
                        n.parentNode.removeChild(n)
                    }
                })
            },
            bindEvents: {
                "ready": function(e) {
                    var me = this;
                    if (window.FormData && window.FileReader) {
                        domUtils.on(me.body, "paste drop", function(e) {
                            var hasImg = false,
                                items;
                            items = e.type == "paste" ? getPasteImage(e) : getDropImage(e);
                            if (items) {
                                var len = items.length,
                                    file;
                                while (len--) {
                                    file = items[len];
                                    if (file.getAsFile) {
                                        file = file.getAsFile()
                                    }
                                    if (file && file.size > 0) {
                                        sendAndInsertFile(file, me);
                                        hasImg = true
                                    }
                                }
                                hasImg && e.preventDefault()
                            }
                        });
                        domUtils.on(me.body, "dragover", function(e) {
                            if (e.dataTransfer.types[0] == "Files") {
                                e.preventDefault()
                            }
                        });
                        utils.cssRule("loading", ".loadingclass{display:inline-block;cursor:default;background: url('" + this.options.themePath + this.options.theme + "/images/loading.gif') no-repeat center center transparent;border:1px solid #cccccc;margin-left:1px;height: 22px;width: 22px;}\n" + ".loaderrorclass{display:inline-block;cursor:default;background: url('" + this.options.themePath + this.options.theme + "/images/loaderror.png') no-repeat center center transparent;border:1px solid #cccccc;margin-right:1px;height: 22px;width: 22px;" + "}", this.document)
                    }
                }
            }
        }
    });
    UE.plugin.register("autosave", function() {
        var me = this,
            lastSaveTime = new Date(),
            MIN_TIME = 20,
            saveKey = null;

        function save(editor) {
            var saveData;
            if (new Date() - lastSaveTime < MIN_TIME) {
                return
            }
            if (!editor.hasContents()) {
                saveKey && me.removePreferences(saveKey);
                return
            }
            lastSaveTime = new Date();
            editor._saveFlag = null;
            saveData = me.body.innerHTML;
            if (editor.fireEvent("beforeautosave", {
                    content: saveData
                }) === false) {
                return
            }
            me.setPreferences(saveKey, saveData);
            editor.fireEvent("afterautosave", {
                content: saveData
            })
        }
        return {
            defaultOptions: {
                saveInterval: 500
            },
            bindEvents: {
                "ready": function() {
                    var _suffix = "-drafts-data",
                        key = null;
                    if (me.key) {
                        key = me.key + _suffix
                    } else {
                        key = (me.container.parentNode.id || "ue-common") + _suffix
                    }
                    saveKey = (location.protocol + location.host + location.pathname).replace(/[.:\/]/g, "_") + key
                },
                "contentchange": function() {
                    if (!saveKey) {
                        return
                    }
                    if (me._saveFlag) {
                        window.clearTimeout(me._saveFlag)
                    }
                    if (me.options.saveInterval > 0) {
                        me._saveFlag = window.setTimeout(function() {
                            save(me)
                        }, me.options.saveInterval)
                    } else {
                        save(me)
                    }
                }
            },
            commands: {
                "clearlocaldata": {
                    execCommand: function(cmd, name) {
                        if (saveKey && me.getPreferences(saveKey)) {
                            me.removePreferences(saveKey)
                        }
                    },
                    notNeedUndo: true,
                    ignoreContentChange: true
                },
                "getlocaldata": {
                    execCommand: function(cmd, name) {
                        return saveKey ? me.getPreferences(saveKey) || "" : ""
                    },
                    notNeedUndo: true,
                    ignoreContentChange: true
                },
                "drafts": {
                    execCommand: function(cmd, name) {
                        if (saveKey) {
                            me.body.innerHTML = me.getPreferences(saveKey) || "<p>" + domUtils.fillHtml + "</p>";
                            me.focus(true)
                        }
                    },
                    queryCommandState: function() {
                        return saveKey ? (me.getPreferences(saveKey) === null ? -1 : 0) : -1
                    },
                    notNeedUndo: true,
                    ignoreContentChange: true
                }
            }
        }
    });
    UE.plugin.register("charts", function() {
        var me = this;
        return {
            bindEvents: {
                "chartserror": function() {}
            },
            commands: {
                "charts": {
                    execCommand: function(cmd, data) {
                        var tableNode = domUtils.findParentByTagName(this.selection.getRange().startContainer, "table", true),
                            flagText = [],
                            config = {};
                        if (!tableNode) {
                            return false
                        }
                        if (!validData(tableNode)) {
                            me.fireEvent("chartserror");
                            return false
                        }
                        config.title = data.title || "";
                        config.subTitle = data.subTitle || "";
                        config.xTitle = data.xTitle || "";
                        config.yTitle = data.yTitle || "";
                        config.suffix = data.suffix || "";
                        config.tip = data.tip || "";
                        config.dataFormat = data.tableDataFormat || "";
                        config.chartType = data.chartType || 0;
                        for (var key in config) {
                            if (!config.hasOwnProperty(key)) {
                                continue
                            }
                            flagText.push(key + ":" + config[key])
                        }
                        tableNode.setAttribute("data-chart", flagText.join(";"));
                        domUtils.addClass(tableNode, "edui-charts-table")
                    },
                    queryCommandState: function(cmd, name) {
                        var tableNode = domUtils.findParentByTagName(this.selection.getRange().startContainer, "table", true);
                        return tableNode && validData(tableNode) ? 0 : -1
                    }
                }
            },
            inputRule: function(root) {
                utils.each(root.getNodesByTagName("table"), function(tableNode) {
                    if (tableNode.getAttr("data-chart") !== undefined) {
                        tableNode.setAttr("style")
                    }
                })
            },
            outputRule: function(root) {
                utils.each(root.getNodesByTagName("table"), function(tableNode) {
                    if (tableNode.getAttr("data-chart") !== undefined) {
                        tableNode.setAttr("style", "display: none;")
                    }
                })
            }
        };

        function validData(table) {
            var firstRows = null,
                cellCount = 0;
            if (table.rows.length < 2) {
                return false
            }
            if (table.rows[0].cells.length < 2) {
                return false
            }
            firstRows = table.rows[0].cells;
            cellCount = firstRows.length;
            for (var i = 0, cell; cell = firstRows[i]; i++) {
                if (cell.tagName.toLowerCase() !== "th") {
                    return false
                }
            }
            for (var i = 1, row; row = table.rows[i]; i++) {
                if (row.cells.length != cellCount) {
                    return false
                }
                if (row.cells[0].tagName.toLowerCase() !== "th") {
                    return false
                }
                for (var j = 1, cell; cell = row.cells[j]; j++) {
                    var value = utils.trim((cell.innerText || cell.textContent || ""));
                    value = value.replace(new RegExp(UE.dom.domUtils.fillChar, "g"), "").replace(/^\s+|\s+$/g, "");
                    if (!/^\d*\.?\d+$/.test(value)) {
                        return false
                    }
                }
            }
            return true
        }
    });
    UE.plugin.register("section", function() {
        function Section(option) {
            this.tag = "";
            this.level = -1, this.dom = null;
            this.nextSection = null;
            this.previousSection = null;
            this.parentSection = null;
            this.startAddress = [];
            this.endAddress = [];
            this.children = []
        }
        function getSection(option) {
            var section = new Section();
            return utils.extend(section, option)
        }
        function getNodeFromAddress(startAddress, root) {
            var current = root;
            for (var i = 0; i < startAddress.length; i++) {
                if (!current.childNodes) {
                    return null
                }
                current = current.childNodes[startAddress[i]]
            }
            return current
        }
        var me = this;
        return {
            bindMultiEvents: {
                type: "aftersetcontent afterscencerestore",
                handler: function() {
                    me.fireEvent("updateSections")
                }
            },
            bindEvents: {
                "ready": function() {
                    me.fireEvent("updateSections");
                    domUtils.on(me.body, "drop paste", function() {
                        me.fireEvent("updateSections")
                    })
                },
                "afterexeccommand": function(type, cmd) {
                    if (cmd == "paragraph") {
                        me.fireEvent("updateSections")
                    }
                },
                "keyup": function(type, e) {
                    var me = this,
                        range = me.selection.getRange();
                    if (range.collapsed != true) {
                        me.fireEvent("updateSections")
                    } else {
                        var keyCode = e.keyCode || e.which;
                        if (keyCode == 13 || keyCode == 8 || keyCode == 46) {
                            me.fireEvent("updateSections")
                        }
                    }
                }
            },
            commands: {
                "getsections": {
                    execCommand: function(cmd, levels) {
                        var levelFn = levels || ["h1", "h2", "h3", "h4", "h5", "h6"];
                        for (var i = 0; i < levelFn.length; i++) {
                            if (typeof levelFn[i] == "string") {
                                levelFn[i] = function(fn) {
                                    return function(node) {
                                        return node.tagName == fn.toUpperCase()
                                    }
                                }(levelFn[i])
                            } else {
                                if (typeof levelFn[i] != "function") {
                                    levelFn[i] = function(node) {
                                        return null
                                    }
                                }
                            }
                        }
                        function getSectionLevel(node) {
                            for (var i = 0; i < levelFn.length; i++) {
                                if (levelFn[i](node)) {
                                    return i
                                }
                            }
                            return -1
                        }
                        var me = this,
                            Directory = getSection({
                                "level": -1,
                                "title": "root"
                            }),
                            previous = Directory;

                        function traversal(node, Directory) {
                            var level, tmpSection = null,
                                parent, child, children = node.childNodes;
                            for (var i = 0, len = children.length; i < len; i++) {
                                child = children[i];
                                level = getSectionLevel(child);
                                if (level >= 0) {
                                    var address = me.selection.getRange().selectNode(child).createAddress(true).startAddress,
                                        current = getSection({
                                            "tag": child.tagName,
                                            "title": child.innerText || child.textContent || "",
                                            "level": level,
                                            "dom": child,
                                            "startAddress": utils.clone(address, []),
                                            "endAddress": utils.clone(address, []),
                                            "children": []
                                        });
                                    previous.nextSection = current;
                                    current.previousSection = previous;
                                    parent = previous;
                                    while (level <= parent.level) {
                                        parent = parent.parentSection
                                    }
                                    current.parentSection = parent;
                                    parent.children.push(current);
                                    tmpSection = previous = current
                                } else {
                                    child.nodeType === 1 && traversal(child, Directory);
                                    tmpSection && tmpSection.endAddress[tmpSection.endAddress.length - 1]++
                                }
                            }
                        }
                        traversal(me.body, Directory);
                        return Directory
                    },
                    notNeedUndo: true
                },
                "movesection": {
                    execCommand: function(cmd, sourceSection, targetSection, isAfter) {
                        var me = this,
                            targetAddress, target;
                        if (!sourceSection || !targetSection || targetSection.level == -1) {
                            return
                        }
                        targetAddress = isAfter ? targetSection.endAddress : targetSection.startAddress;
                        target = getNodeFromAddress(targetAddress, me.body);
                        if (!targetAddress || !target || isContainsAddress(sourceSection.startAddress, sourceSection.endAddress, targetAddress)) {
                            return
                        }
                        var startNode = getNodeFromAddress(sourceSection.startAddress, me.body),
                            endNode = getNodeFromAddress(sourceSection.endAddress, me.body),
                            current, nextNode;
                        if (isAfter) {
                            current = endNode;
                            while (current && !(domUtils.getPosition(startNode, current) & domUtils.POSITION_FOLLOWING)) {
                                nextNode = current.previousSibling;
                                domUtils.insertAfter(target, current);
                                if (current == startNode) {
                                    break
                                }
                                current = nextNode
                            }
                        } else {
                            current = startNode;
                            while (current && !(domUtils.getPosition(current, endNode) & domUtils.POSITION_FOLLOWING)) {
                                nextNode = current.nextSibling;
                                target.parentNode.insertBefore(current, target);
                                if (current == endNode) {
                                    break
                                }
                                current = nextNode
                            }
                        }
                        me.fireEvent("updateSections");

                        function isContainsAddress(startAddress, endAddress, addressTarget) {
                            var isAfterStartAddress = false,
                                isBeforeEndAddress = false;
                            for (var i = 0; i < startAddress.length; i++) {
                                if (i >= addressTarget.length) {
                                    break
                                }
                                if (addressTarget[i] > startAddress[i]) {
                                    isAfterStartAddress = true;
                                    break
                                } else {
                                    if (addressTarget[i] < startAddress[i]) {
                                        break
                                    }
                                }
                            }
                            for (var i = 0; i < endAddress.length; i++) {
                                if (i >= addressTarget.length) {
                                    break
                                }
                                if (addressTarget[i] < startAddress[i]) {
                                    isBeforeEndAddress = true;
                                    break
                                } else {
                                    if (addressTarget[i] > startAddress[i]) {
                                        break
                                    }
                                }
                            }
                            return isAfterStartAddress && isBeforeEndAddress
                        }
                    }
                },
                "deletesection": {
                    execCommand: function(cmd, section, keepChildren) {
                        var me = this;
                        if (!section) {
                            return
                        }
                        function getNodeFromAddress(startAddress) {
                            var current = me.body;
                            for (var i = 0; i < startAddress.length; i++) {
                                if (!current.childNodes) {
                                    return null
                                }
                                current = current.childNodes[startAddress[i]]
                            }
                            return current
                        }
                        var startNode = getNodeFromAddress(section.startAddress),
                            endNode = getNodeFromAddress(section.endAddress),
                            current = startNode,
                            nextNode;
                        if (!keepChildren) {
                            while (current && domUtils.inDoc(endNode, me.document) && !(domUtils.getPosition(current, endNode) & domUtils.POSITION_FOLLOWING)) {
                                nextNode = current.nextSibling;
                                domUtils.remove(current);
                                current = nextNode
                            }
                        } else {
                            domUtils.remove(current)
                        }
                        me.fireEvent("updateSections")
                    }
                },
                "selectsection": {
                    execCommand: function(cmd, section) {
                        if (!section && !section.dom) {
                            return false
                        }
                        var me = this,
                            range = me.selection.getRange(),
                            address = {
                                "startAddress": utils.clone(section.startAddress, []),
                                "endAddress": utils.clone(section.endAddress, [])
                            };
                        address.endAddress[address.endAddress.length - 1]++;
                        range.moveToAddress(address).select().scrollToView();
                        return true
                    },
                    notNeedUndo: true
                },
                "scrolltosection": {
                    execCommand: function(cmd, section) {
                        if (!section && !section.dom) {
                            return false
                        }
                        var me = this,
                            range = me.selection.getRange(),
                            address = {
                                "startAddress": section.startAddress,
                                "endAddress": section.endAddress
                            };
                        address.endAddress[address.endAddress.length - 1]++;
                        range.moveToAddress(address).scrollToView();
                        return true
                    },
                    notNeedUndo: true
                }
            }
        }
    });
    UE.plugin.register("simpleupload", function() {
        var me = this,
            isLoaded = false,
            containerBtn;

        function initUploadBtn() {
            var w = containerBtn.offsetWidth || 20,
                h = containerBtn.offsetHeight || 20,
                btnIframe = document.createElement("iframe"),
                btnStyle = "display:block;width:" + w + "px;height:" + h + "px;overflow:hidden;border:0;margin:0;padding:0;position:absolute;top:0;left:0;filter:alpha(opacity=0);-moz-opacity:0;-khtml-opacity: 0;opacity: 0;cursor:pointer;";
            domUtils.on(btnIframe, "load", function() {
                var timestrap = (+new Date()).toString(36),
                    wrapper, btnIframeDoc, btnIframeBody;
                btnIframeDoc = (btnIframe.contentDocument || btnIframe.contentWindow.document);
                btnIframeBody = btnIframeDoc.body;
                wrapper = btnIframeDoc.createElement("div");
                wrapper.innerHTML = '<form id="edui_form_' + timestrap + '" target="edui_iframe_' + timestrap + '" method="POST" enctype="multipart/form-data" action="' + me.getOpt("serverUrl") + '" ' + 'style="' + btnStyle + '">' + '<input id="edui_input_' + timestrap + '" type="file" accept="image/*" name="' + me.options.imageFieldName + '" ' + 'style="' + btnStyle + '">' + "</form>" + '<iframe id="edui_iframe_' + timestrap + '" name="edui_iframe_' + timestrap + '" style="display:none;width:0;height:0;border:0;margin:0;padding:0;position:absolute;"></iframe>' + '<div id="edui_div_' + timestrap + '" name="edui_div_' + timestrap + '" style="display:none;width:0;height:0;border:0;margin:0;padding:0;position:absolute;"></div>';
                wrapper.className = "edui-" + me.options.theme;
                wrapper.id = me.ui.id + "_iframeupload";
                btnIframeBody.style.cssText = btnStyle;
                btnIframeBody.style.width = w + "px";
                btnIframeBody.style.height = h + "px";
                btnIframeBody.appendChild(wrapper);
                if (btnIframeBody.parentNode) {
                    btnIframeBody.parentNode.style.width = w + "px";
                    btnIframeBody.parentNode.style.height = w + "px"
                }
                var form = btnIframeDoc.getElementById("edui_form_" + timestrap);
                var input = btnIframeDoc.getElementById("edui_input_" + timestrap);
                var iframe = btnIframeDoc.getElementById("edui_iframe_" + timestrap);
                var eduiDiv = btnIframeDoc.getElementById("edui_div_" + timestrap);
                domUtils.on(input, "change", function() {
                    if (!input.value) {
                        return
                    }
                    var loadingId = "loading_" + (+new Date()).toString(36);
                    var imageActionUrl = me.getActionUrl(me.getOpt("imageActionName"));
                    var allowFiles = me.getOpt("imageAllowFiles");
                    me.focus();
                    me.execCommand("inserthtml", '<img class="loadingclass" id="' + loadingId + '" src="' + me.options.themePath + me.options.theme + '/images/spacer.gif" title="' + (me.getLang("simpleupload.loading") || "") + '" >');
                    if (!me.getOpt("imageActionName")) {
                        errorHandler(me.getLang("autoupload.errorLoadConfig"));
                        return
                    }
                    var filename = input.value,
                        fileext = filename ? filename.substr(filename.lastIndexOf(".")) : "";
                    if (!fileext || (allowFiles && (allowFiles.join("") + ".").indexOf(fileext.toLowerCase() + ".") == -1)) {
                        showErrorLoader(me.getLang("simpleupload.exceedTypeError"));
                        return
                    }
                    var params = utils.serializeParam(me.queryCommandValue("serverparam")) || "";
                    var action = utils.formatUrl(imageActionUrl + (imageActionUrl.indexOf("?") == -1 ? "?" : "&") + params);
                    var formData = new FormData();
                    formData.append("upfile", form[0].files[0]);
                    $.ajax({
                        url: action,
                        type: "POST",
                        cache: false,
                        data: formData,
                        processData: false,
                        contentType: false,
                        success: function(data) {
                            var link, loader, body = (iframe.contentDocument || iframe.contentWindow.document).body,
                                result = body.innerText || body.textContent || "";
                            link = me.options.imageUrlPrefix + data.url;
                            if (data.state == "SUCCESS" && data.url) {
                                loader = me.document.getElementById(loadingId);
                                loader.setAttribute("src", link);
                                loader.setAttribute("_src", link);
                                loader.setAttribute("title", data.title || "");
                                loader.setAttribute("alt", data.original || "");
                                loader.removeAttribute("id");
                                domUtils.removeClasses(loader, "loadingclass")
                            } else {
                                showErrorLoader && showErrorLoader(data.state)
                            }
                            form.reset()
                        }
                    });

                    function showErrorLoader(title) {
                        if (loadingId) {
                            var loader = me.document.getElementById(loadingId);
                            loader && domUtils.remove(loader);
                            me.fireEvent("showmessage", {
                                "id": loadingId,
                                "content": title,
                                "type": "error",
                                "timeout": 4000
                            })
                        }
                    }
                });
                var stateTimer;
                me.addListener("selectionchange", function() {
                    clearTimeout(stateTimer);
                    stateTimer = setTimeout(function() {
                        var state = me.queryCommandState("simpleupload");
                        if (state == -1) {
                            input.disabled = "disabled"
                        } else {
                            input.disabled = false
                        }
                    }, 400)
                });
                isLoaded = true
            });
            btnIframe.style.cssText = btnStyle;
            containerBtn.appendChild(btnIframe)
        }
        return {
            bindEvents: {
                "ready": function() {
                    utils.cssRule("loading", ".loadingclass{display:inline-block;cursor:default;background: url('" + this.options.themePath + this.options.theme + "/images/loading.gif') no-repeat center center transparent;border:1px solid #cccccc;margin-right:1px;height: 22px;width: 22px;}\n" + ".loaderrorclass{display:inline-block;cursor:default;background: url('" + this.options.themePath + this.options.theme + "/images/loaderror.png') no-repeat center center transparent;border:1px solid #cccccc;margin-right:1px;height: 22px;width: 22px;" + "}", this.document)
                },
                "simpleuploadbtnready": function(type, container) {
                    containerBtn = container;
                    me.afterConfigReady(initUploadBtn)
                }
            },
            outputRule: function(root) {
                utils.each(root.getNodesByTagName("img"), function(n) {
                    if (/\b(loaderrorclass)|(bloaderrorclass)\b/.test(n.getAttr("class"))) {
                        n.parentNode.removeChild(n)
                    }
                })
            },
            commands: {
                "simpleupload": {
                    queryCommandState: function() {
                        return isLoaded ? 0 : -1
                    }
                }
            }
        }
    });
    UE.plugin.register("serverparam", function() {
        var me = this,
            serverParam = {};
        return {
            commands: {
                "serverparam": {
                    execCommand: function(cmd, key, value) {
                        if (key === undefined || key === null) {
                            serverParam = {}
                        } else {
                            if (utils.isString(key)) {
                                if (value === undefined || value === null) {
                                    delete serverParam[key]
                                } else {
                                    serverParam[key] = value
                                }
                            } else {
                                if (utils.isObject(key)) {
                                    utils.extend(serverParam, key, true)
                                } else {
                                    if (utils.isFunction(key)) {
                                        utils.extend(serverParam, key(), true)
                                    }
                                }
                            }
                        }
                    },
                    queryCommandValue: function() {
                        return serverParam || {}
                    }
                }
            }
        }
    });
    UE.plugin.register("insertfile", function() {
        var me = this;

        function getFileIcon(url) {
            var ext = url.substr(url.lastIndexOf(".") + 1).toLowerCase(),
                maps = {
                    "rar": "icon_rar.gif",
                    "zip": "icon_rar.gif",
                    "tar": "icon_rar.gif",
                    "gz": "icon_rar.gif",
                    "bz2": "icon_rar.gif",
                    "doc": "icon_doc.gif",
                    "docx": "icon_doc.gif",
                    "pdf": "icon_pdf.gif",
                    "mp3": "icon_mp3.gif",
                    "xls": "icon_xls.gif",
                    "chm": "icon_chm.gif",
                    "ppt": "icon_ppt.gif",
                    "pptx": "icon_ppt.gif",
                    "avi": "icon_mv.gif",
                    "rmvb": "icon_mv.gif",
                    "wmv": "icon_mv.gif",
                    "flv": "icon_mv.gif",
                    "swf": "icon_mv.gif",
                    "rm": "icon_mv.gif",
                    "exe": "icon_exe.gif",
                    "psd": "icon_psd.gif",
                    "txt": "icon_txt.gif",
                    "jpg": "icon_jpg.gif",
                    "png": "icon_jpg.gif",
                    "jpeg": "icon_jpg.gif",
                    "gif": "icon_jpg.gif",
                    "ico": "icon_jpg.gif",
                    "bmp": "icon_jpg.gif"
                };
            return maps[ext] ? maps[ext] : maps["txt"]
        }
        return {
            commands: {
                "insertfile": {
                    execCommand: function(command, filelist) {
                        filelist = utils.isArray(filelist) ? filelist : [filelist];
                        var i, item, icon, title, html = "",
                            URL = me.getOpt("UEDITOR_HOME_URL"),
                            iconDir = URL + (URL.substr(URL.length - 1) == "/" ? "" : "/") + "dialogs/attachment/fileTypeImages/";
                        for (i = 0; i < filelist.length; i++) {
                            item = filelist[i];
                            icon = iconDir + getFileIcon(item.url);
                            title = item.title || item.url.substr(item.url.lastIndexOf("/") + 1);
                            html += '<p style="line-height: 16px;">' + '<img style="vertical-align: middle; margin-right: 2px;" src="' + icon + '" _src="' + icon + '" />' + '<a style="font-size:12px; color:#0066cc;" href="' + item.url + '" title="' + title + '">' + title + "</a>" + "</p>"
                        }
                        me.execCommand("insertHtml", html)
                    }
                }
            }
        }
    });
    UE.plugins.xssFilter = function() {
        var config = UEDITOR_CONFIG;
        var whitList = config.whitList;

        function filter(node) {
            var tagName = node.tagName;
            var attrs = node.attrs;
            if (!whitList.hasOwnProperty(tagName)) {
                node.parentNode.removeChild(node);
                return false
            }
            UE.utils.each(attrs, function(val, key) {
                if (whitList[tagName].indexOf(key) === -1) {
                    node.setAttr(key)
                }
            })
        }
        if (whitList && config.xssFilterRules) {
            this.options.filterRules = function() {
                var result = {};
                UE.utils.each(whitList, function(val, key) {
                    result[key] = function(node) {
                        return filter(node)
                    }
                });
                return result
            }()
        }
        var tagList = [];
        UE.utils.each(whitList, function(val, key) {
            tagList.push(key)
        });
        if (whitList && config.inputXssFilter) {
            this.addInputRule(function(root) {
                root.traversal(function(node) {
                    if (node.type !== "element") {
                        return false
                    }
                    filter(node)
                })
            })
        }
        if (whitList && config.outputXssFilter) {
            this.addOutputRule(function(root) {
                root.traversal(function(node) {
                    if (node.type !== "element") {
                        return false
                    }
                    filter(node)
                })
            })
        }
    };
    var baidu = baidu || {};
    baidu.editor = baidu.editor || {};
    UE.ui = baidu.editor.ui = {};
    (function() {
        var browser = baidu.editor.browser,
            domUtils = baidu.editor.dom.domUtils;
        var magic = "$EDITORUI";
        var root = window[magic] = {};
        var uidMagic = "ID" + magic;
        var uidCount = 0;
        var uiUtils = baidu.editor.ui.uiUtils = {
            uid: function(obj) {
                return (obj ? obj[uidMagic] || (obj[uidMagic] = ++uidCount) : ++uidCount)
            },
            hook: function(fn, callback) {
                var dg;
                if (fn && fn._callbacks) {
                    dg = fn
                } else {
                    dg = function() {
                        var q;
                        if (fn) {
                            q = fn.apply(this, arguments)
                        }
                        var callbacks = dg._callbacks;
                        var k = callbacks.length;
                        while (k--) {
                            var r = callbacks[k].apply(this, arguments);
                            if (q === undefined) {
                                q = r
                            }
                        }
                        return q
                    };
                    dg._callbacks = []
                }
                dg._callbacks.push(callback);
                return dg
            },
            createElementByHtml: function(html) {
                var el = document.createElement("div");
                el.innerHTML = html;
                el = el.firstChild;
                el.parentNode.removeChild(el);
                return el
            },
            getViewportElement: function() {
                return (browser.ie && browser.quirks) ? document.body : document.documentElement
            },
            getClientRect: function(element) {
                var bcr;
                try {
                    bcr = element.getBoundingClientRect()
                } catch (e) {
                    bcr = {
                        left: 0,
                        top: 0,
                        height: 0,
                        width: 0
                    }
                }
                var rect = {
                    left: Math.round(bcr.left),
                    top: Math.round(bcr.top),
                    height: Math.round(bcr.bottom - bcr.top),
                    width: Math.round(bcr.right - bcr.left)
                };
                var doc;
                while ((doc = element.ownerDocument) !== document && (element = domUtils.getWindow(doc).frameElement)) {
                    bcr = element.getBoundingClientRect();
                    rect.left += bcr.left;
                    rect.top += bcr.top
                }
                rect.bottom = rect.top + rect.height;
                rect.right = rect.left + rect.width;
                return rect
            },
            getViewportRect: function() {
                var viewportEl = uiUtils.getViewportElement();
                var width = (window.innerWidth || viewportEl.clientWidth) | 0;
                var height = (window.innerHeight || viewportEl.clientHeight) | 0;
                return {
                    left: 0,
                    top: 0,
                    height: height,
                    width: width,
                    bottom: height,
                    right: width
                }
            },
            setViewportOffset: function(element, offset) {
                var rect;
                var fixedLayer = uiUtils.getFixedLayer();
                if (element.parentNode === fixedLayer) {
                    element.style.left = offset.left + "px";
                    element.style.top = offset.top + "px"
                } else {
                    domUtils.setViewportOffset(element, offset)
                }
            },
            getEventOffset: function(evt) {
                var el = evt.target || evt.srcElement;
                var rect = uiUtils.getClientRect(el);
                var offset = uiUtils.getViewportOffsetByEvent(evt);
                return {
                    left: offset.left - rect.left,
                    top: offset.top - rect.top
                }
            },
            getViewportOffsetByEvent: function(evt) {
                var el = evt.target || evt.srcElement;
                var frameEl = domUtils.getWindow(el).frameElement;
                var offset = {
                    left: evt.clientX,
                    top: evt.clientY
                };
                if (frameEl && el.ownerDocument !== document) {
                    var rect = uiUtils.getClientRect(frameEl);
                    offset.left += rect.left;
                    offset.top += rect.top
                }
                return offset
            },
            setGlobal: function(id, obj) {
                root[id] = obj;
                return magic + '["' + id + '"]'
            },
            unsetGlobal: function(id) {
                delete root[id]
            },
            copyAttributes: function(tgt, src) {
                var attributes = src.attributes;
                var k = attributes.length;
                while (k--) {
                    var attrNode = attributes[k];
                    if (attrNode.nodeName != "style" && attrNode.nodeName != "class" && (!browser.ie || attrNode.specified)) {
                        tgt.setAttribute(attrNode.nodeName, attrNode.nodeValue)
                    }
                }
                if (src.className) {
                    domUtils.addClass(tgt, src.className)
                }
                if (src.style.cssText) {
                    tgt.style.cssText += ";" + src.style.cssText
                }
            },
            removeStyle: function(el, styleName) {
                if (el.style.removeProperty) {
                    el.style.removeProperty(styleName)
                } else {
                    if (el.style.removeAttribute) {
                        el.style.removeAttribute(styleName)
                    } else {
                        throw ""
                    }
                }
            },
            contains: function(elA, elB) {
                return elA && elB && (elA === elB ? false : (elA.contains ? elA.contains(elB) : elA.compareDocumentPosition(elB) & 16))
            },
            startDrag: function(evt, callbacks, doc) {
                var doc = doc || document;
                var startX = evt.clientX;
                var startY = evt.clientY;

                function handleMouseMove(evt) {
                    var x = evt.clientX - startX;
                    var y = evt.clientY - startY;
                    callbacks.ondragmove(x, y, evt);
                    if (evt.stopPropagation) {
                        evt.stopPropagation()
                    } else {
                        evt.cancelBubble = true
                    }
                }
                if (doc.addEventListener) {
                    function handleMouseUp(evt) {
                        doc.removeEventListener("mousemove", handleMouseMove, true);
                        doc.removeEventListener("mouseup", handleMouseUp, true);
                        window.removeEventListener("mouseup", handleMouseUp, true);
                        callbacks.ondragstop()
                    }
                    doc.addEventListener("mousemove", handleMouseMove, true);
                    doc.addEventListener("mouseup", handleMouseUp, true);
                    window.addEventListener("mouseup", handleMouseUp, true);
                    evt.preventDefault()
                } else {
                    var elm = evt.srcElement;
                    elm.setCapture();

                    function releaseCaptrue() {
                        elm.releaseCapture();
                        elm.detachEvent("onmousemove", handleMouseMove);
                        elm.detachEvent("onmouseup", releaseCaptrue);
                        elm.detachEvent("onlosecaptrue", releaseCaptrue);
                        callbacks.ondragstop()
                    }
                    elm.attachEvent("onmousemove", handleMouseMove);
                    elm.attachEvent("onmouseup", releaseCaptrue);
                    elm.attachEvent("onlosecaptrue", releaseCaptrue);
                    evt.returnValue = false
                }
                callbacks.ondragstart()
            },
            getFixedLayer: function() {
                var layer = document.getElementById("edui_fixedlayer");
                if (layer == null) {
                    layer = document.createElement("div");
                    layer.id = "edui_fixedlayer";
                    document.body.appendChild(layer);
                    if (browser.ie && browser.version <= 8) {
                        layer.style.position = "absolute";
                        bindFixedLayer();
                        setTimeout(updateFixedOffset)
                    } else {
                        layer.style.position = "fixed"
                    }
                    layer.style.left = "0";
                    layer.style.top = "0";
                    layer.style.width = "0";
                    layer.style.height = "0"
                }
                return layer
            },
            makeUnselectable: function(element) {
                if (browser.opera || (browser.ie && browser.version < 9)) {
                    element.unselectable = "on";
                    if (element.hasChildNodes()) {
                        for (var i = 0; i < element.childNodes.length; i++) {
                            if (element.childNodes[i].nodeType == 1) {
                                uiUtils.makeUnselectable(element.childNodes[i])
                            }
                        }
                    }
                } else {
                    if (element.style.MozUserSelect !== undefined) {
                        element.style.MozUserSelect = "none"
                    } else {
                        if (element.style.WebkitUserSelect !== undefined) {
                            element.style.WebkitUserSelect = "none"
                        } else {
                            if (element.style.KhtmlUserSelect !== undefined) {
                                element.style.KhtmlUserSelect = "none"
                            }
                        }
                    }
                }
            }
        };

        function updateFixedOffset() {
            var layer = document.getElementById("edui_fixedlayer");
            uiUtils.setViewportOffset(layer, {
                left: 0,
                top: 0
            })
        }
        function bindFixedLayer(adjOffset) {
            domUtils.on(window, "scroll", updateFixedOffset);
            domUtils.on(window, "resize", baidu.editor.utils.defer(updateFixedOffset, 0, true))
        }
    })();
    (function() {
        var utils = baidu.editor.utils,
            uiUtils = baidu.editor.ui.uiUtils,
            EventBase = baidu.editor.EventBase,
            UIBase = baidu.editor.ui.UIBase = function() {};
        UIBase.prototype = {
            className: "",
            uiName: "",
            initOptions: function(options) {
                var me = this;
                for (var k in options) {
                    me[k] = options[k]
                }
                this.id = this.id || "edui" + uiUtils.uid()
            },
            initUIBase: function() {
                this._globalKey = utils.unhtml(uiUtils.setGlobal(this.id, this))
            },
            render: function(holder) {
                var html = this.renderHtml();
                var el = uiUtils.createElementByHtml(html);
                var list = domUtils.getElementsByTagName(el, "*");
                var theme = "edui-" + (this.theme || this.editor.options.theme);
                var layer = document.getElementById("edui_fixedlayer");
                for (var i = 0, node; node = list[i++];) {
                    domUtils.addClass(node, theme)
                }
                domUtils.addClass(el, theme);
                if (layer) {
                    layer.className = "";
                    domUtils.addClass(layer, theme)
                }
                var seatEl = this.getDom();
                if (seatEl != null) {
                    seatEl.parentNode.replaceChild(el, seatEl);
                    uiUtils.copyAttributes(el, seatEl)
                } else {
                    if (typeof holder == "string") {
                        holder = document.getElementById(holder)
                    }
                    holder = holder || uiUtils.getFixedLayer();
                    domUtils.addClass(holder, theme);
                    holder.appendChild(el)
                }
                this.postRender()
            },
            getDom: function(name) {
                if (!name) {
                    return document.getElementById(this.id)
                } else {
                    return document.getElementById(this.id + "_" + name)
                }
            },
            postRender: function() {
                this.fireEvent("postrender")
            },
            getHtmlTpl: function() {
                return ""
            },
            formatHtml: function(tpl) {
                var prefix = "edui-" + this.uiName;
                return (tpl.replace(/##/g, this.id).replace(/%%-/g, this.uiName ? prefix + "-" : "").replace(/%%/g, (this.uiName ? prefix : "") + " " + this.className).replace(/\$\$/g, this._globalKey))
            },
            renderHtml: function() {
                return this.formatHtml(this.getHtmlTpl())
            },
            dispose: function() {
                var box = this.getDom();
                if (box) {
                    baidu.editor.dom.domUtils.remove(box)
                }
                uiUtils.unsetGlobal(this.id)
            }
        };
        utils.inherits(UIBase, EventBase)
    })();
    (function() {
        var utils = baidu.editor.utils,
            UIBase = baidu.editor.ui.UIBase,
            Separator = baidu.editor.ui.Separator = function(options) {
                this.initOptions(options);
                this.initSeparator()
            };
        Separator.prototype = {
            uiName: "separator",
            initSeparator: function() {
                this.initUIBase()
            },
            getHtmlTpl: function() {
                return '<div id="##" class="edui-box %%"></div>'
            }
        };
        utils.inherits(Separator, UIBase)
    })();
    (function() {
        var utils = baidu.editor.utils,
            domUtils = baidu.editor.dom.domUtils,
            UIBase = baidu.editor.ui.UIBase,
            uiUtils = baidu.editor.ui.uiUtils;
        var Mask = baidu.editor.ui.Mask = function(options) {
            this.initOptions(options);
            this.initUIBase()
        };
        Mask.prototype = {
            getHtmlTpl: function() {
                return '<div id="##" class="edui-mask %%" onclick="return $$._onClick(event, this);" onmousedown="return $$._onMouseDown(event, this);"></div>'
            },
            postRender: function() {
                var me = this;
                domUtils.on(window, "resize", function() {
                    setTimeout(function() {
                        if (!me.isHidden()) {
                            me._fill()
                        }
                    })
                })
            },
            show: function(zIndex) {
                this._fill();
                this.getDom().style.display = "";
                this.getDom().style.zIndex = zIndex
            },
            hide: function() {
                this.getDom().style.display = "none";
                this.getDom().style.zIndex = ""
            },
            isHidden: function() {
                return this.getDom().style.display == "none"
            },
            _onMouseDown: function() {
                return false
            },
            _onClick: function(e, target) {
                this.fireEvent("click", e, target)
            },
            _fill: function() {
                var el = this.getDom();
                var vpRect = uiUtils.getViewportRect();
                el.style.width = vpRect.width + "px";
                el.style.height = vpRect.height + "px"
            }
        };
        utils.inherits(Mask, UIBase)
    })();
    (function() {
        var utils = baidu.editor.utils,
            uiUtils = baidu.editor.ui.uiUtils,
            domUtils = baidu.editor.dom.domUtils,
            UIBase = baidu.editor.ui.UIBase,
            Popup = baidu.editor.ui.Popup = function(options) {
                this.initOptions(options);
                this.initPopup()
            };
        var allPopups = [];

        function closeAllPopup(evt, el) {
            for (var i = 0; i < allPopups.length; i++) {
                var pop = allPopups[i];
                if (!pop.isHidden()) {
                    if (pop.queryAutoHide(el) !== false) {
                        if (evt && /scroll/ig.test(evt.type) && pop.className == "edui-wordpastepop") {
                            return
                        }
                        pop.hide()
                    }
                }
            }
            if (allPopups.length) {
                pop.editor.fireEvent("afterhidepop")
            }
        }
        Popup.postHide = closeAllPopup;
        var ANCHOR_CLASSES = ["edui-anchor-topleft", "edui-anchor-topright", "edui-anchor-bottomleft", "edui-anchor-bottomright"];
        Popup.prototype = {
            SHADOW_RADIUS: 5,
            content: null,
            _hidden: false,
            autoRender: true,
            canSideLeft: true,
            canSideUp: true,
            initPopup: function() {
                this.initUIBase();
                allPopups.push(this)
            },
            getHtmlTpl: function() {
                return '<div id="##" class="edui-popup %%" onmousedown="return false;">' + ' <div id="##_body" class="edui-popup-body">' + ' <iframe style="position:absolute;z-index:-1;left:0;top:0;background-color: transparent;" frameborder="0" width="100%" height="100%" src="about:blank"></iframe>' + ' <div class="edui-shadow"></div>' + ' <div id="##_content" class="edui-popup-content">' + this.getContentHtmlTpl() + "  </div>" + " </div>" + "</div>"
            },
            getContentHtmlTpl: function() {
                if (this.content) {
                    if (typeof this.content == "string") {
                        return this.content
                    }
                    return this.content.renderHtml()
                } else {
                    return ""
                }
            },
            _UIBase_postRender: UIBase.prototype.postRender,
            postRender: function() {
                if (this.content instanceof UIBase) {
                    this.content.postRender()
                }
                if (this.captureWheel && !this.captured) {
                    this.captured = true;
                    var winHeight = (document.documentElement.clientHeight || document.body.clientHeight) - 80,
                        _height = this.getDom().offsetHeight,
                        _top = uiUtils.getClientRect(this.combox.getDom()).top,
                        content = this.getDom("content"),
                        ifr = this.getDom("body").getElementsByTagName("iframe"),
                        me = this;
                    ifr.length && (ifr = ifr[0]);
                    while (_top + _height > winHeight) {
                        _height -= 30
                    }
                    content.style.height = _height + "px";
                    ifr && (ifr.style.height = _height + "px");
                    if (window.XMLHttpRequest) {
                        domUtils.on(content, ("onmousewheel" in document.body) ? "mousewheel" : "DOMMouseScroll", function(e) {
                            if (e.preventDefault) {
                                e.preventDefault()
                            } else {
                                e.returnValue = false
                            }
                            if (e.wheelDelta) {
                                content.scrollTop -= (e.wheelDelta / 120) * 60
                            } else {
                                content.scrollTop -= (e.detail / -3) * 60
                            }
                        })
                    } else {
                        domUtils.on(this.getDom(), "mousewheel", function(e) {
                            e.returnValue = false;
                            me.getDom("content").scrollTop -= (e.wheelDelta / 120) * 60
                        })
                    }
                }
                this.fireEvent("postRenderAfter");
                this.hide(true);
                this._UIBase_postRender()
            },
            _doAutoRender: function() {
                if (!this.getDom() && this.autoRender) {
                    this.render()
                }
            },
            mesureSize: function() {
                var box = this.getDom("content");
                return uiUtils.getClientRect(box)
            },
            fitSize: function() {
                if (this.captureWheel && this.sized) {
                    return this.__size
                }
                this.sized = true;
                var popBodyEl = this.getDom("body");
                popBodyEl.style.width = "";
                popBodyEl.style.height = "";
                var size = this.mesureSize();
                if (this.captureWheel) {
                    popBodyEl.style.width = -(-20 - size.width) + "px";
                    var height = parseInt(this.getDom("content").style.height, 10);
                    !window.isNaN(height) && (size.height = height)
                } else {
                    popBodyEl.style.width = size.width + "px"
                }
                popBodyEl.style.height = size.height + "px";
                this.__size = size;
                this.captureWheel && (this.getDom("content").style.overflow = "auto");
                return size
            },
            showAnchor: function(element, hoz) {
                this.showAnchorRect(uiUtils.getClientRect(element), hoz)
            },
            showAnchorRect: function(rect, hoz, adj) {
                this._doAutoRender();
                var vpRect = uiUtils.getViewportRect();
                this.getDom().style.visibility = "hidden";
                this._show();
                var popSize = this.fitSize();
                var sideLeft, sideUp, left, top;
                if (hoz) {
                    sideLeft = this.canSideLeft && (rect.right + popSize.width > vpRect.right && rect.left > popSize.width);
                    sideUp = this.canSideUp && (rect.top + popSize.height > vpRect.bottom && rect.bottom > popSize.height);
                    left = (sideLeft ? rect.left - popSize.width : rect.right);
                    top = (sideUp ? rect.bottom - popSize.height : rect.top)
                } else {
                    sideLeft = this.canSideLeft && (rect.right + popSize.width > vpRect.right && rect.left > popSize.width);
                    sideUp = this.canSideUp && (rect.top + popSize.height > vpRect.bottom && rect.bottom > popSize.height);
                    left = (sideLeft ? rect.right - popSize.width : rect.left);
                    top = (sideUp ? rect.top - popSize.height : rect.bottom)
                }
                var popEl = this.getDom();
                uiUtils.setViewportOffset(popEl, {
                    left: left,
                    top: top
                });
                domUtils.removeClasses(popEl, ANCHOR_CLASSES);
                popEl.className += " " + ANCHOR_CLASSES[(sideUp ? 1 : 0) * 2 + (sideLeft ? 1 : 0)];
                if (this.editor) {
                    popEl.style.zIndex = this.editor.container.style.zIndex * 1 + 10;
                    baidu.editor.ui.uiUtils.getFixedLayer().style.zIndex = popEl.style.zIndex - 1
                }
                this.getDom().style.visibility = "visible"
            },
            showAt: function(offset) {
                var left = offset.left;
                var top = offset.top;
                var rect = {
                    left: left,
                    top: top,
                    right: left,
                    bottom: top,
                    height: 0,
                    width: 0
                };
                this.showAnchorRect(rect, false, true)
            },
            _show: function() {
                if (this._hidden) {
                    var box = this.getDom();
                    box.style.display = "";
                    this._hidden = false;
                    this.fireEvent("show")
                }
            },
            isHidden: function() {
                return this._hidden
            },
            show: function() {
                this._doAutoRender();
                this._show()
            },
            hide: function(notNofity) {
                if (!this._hidden && this.getDom()) {
                    this.getDom().style.display = "none";
                    this._hidden = true;
                    if (!notNofity) {
                        this.fireEvent("hide")
                    }
                }
            },
            queryAutoHide: function(el) {
                return !el || !uiUtils.contains(this.getDom(), el)
            }
        };
        utils.inherits(Popup, UIBase);
        domUtils.on(document, "mousedown", function(evt) {
            var el = evt.target || evt.srcElement;
            closeAllPopup(evt, el)
        });
        domUtils.on(window, "scroll", function(evt, el) {
            closeAllPopup(evt, el)
        })
    })();
    (function() {
        var utils = baidu.editor.utils,
            UIBase = baidu.editor.ui.UIBase,
            ColorPicker = baidu.editor.ui.ColorPicker = function(options) {
                this.initOptions(options);
                this.noColorText = this.noColorText || this.editor.getLang("clearColor");
                this.initUIBase()
            };
        ColorPicker.prototype = {
            getHtmlTpl: function() {
                return genColorPicker(this.noColorText, this.editor)
            },
            _onTableClick: function(evt) {
                var tgt = evt.target || evt.srcElement;
                var color = tgt.getAttribute("data-color");
                if (color) {
                    this.fireEvent("pickcolor", color)
                }
            },
            _onTableOver: function(evt) {
                var tgt = evt.target || evt.srcElement;
                var color = tgt.getAttribute("data-color");
                if (color) {
                    this.getDom("preview").style.backgroundColor = color
                }
            },
            _onTableOut: function() {
                this.getDom("preview").style.backgroundColor = ""
            },
            _onPickNoColor: function() {
                this.fireEvent("picknocolor")
            }
        };
        utils.inherits(ColorPicker, UIBase);
        var COLORS = ("ffffff,000000,eeece1,1f497d,4f81bd,c0504d,9bbb59,8064a2,4bacc6,f79646," + "f2f2f2,7f7f7f,ddd9c3,c6d9f0,dbe5f1,f2dcdb,ebf1dd,e5e0ec,dbeef3,fdeada," + "d8d8d8,595959,c4bd97,8db3e2,b8cce4,e5b9b7,d7e3bc,ccc1d9,b7dde8,fbd5b5," + "bfbfbf,3f3f3f,938953,548dd4,95b3d7,d99694,c3d69b,b2a2c7,92cddc,fac08f," + "a5a5a5,262626,494429,17365d,366092,953734,76923c,5f497a,31859b,e36c09," + "7f7f7f,0c0c0c,1d1b10,0f243e,244061,632423,4f6128,3f3151,205867,974806," + "c00000,ff0000,ffc000,ffff00,92d050,00b050,00b0f0,0070c0,002060,7030a0,").split(",");

        function genColorPicker(noColorText, editor) {
            var html = '<div id="##" class="edui-colorpicker %%">' + '<div class="edui-colorpicker-topbar edui-clearfix">' + '<div unselectable="on" id="##_preview" class="edui-colorpicker-preview"></div>' + '<div unselectable="on" class="edui-colorpicker-nocolor" onclick="$$._onPickNoColor(event, this);">' + noColorText + "</div>" + "</div>" + '<table  class="edui-box" style="border-collapse: collapse;" onmouseover="$$._onTableOver(event, this);" onmouseout="$$._onTableOut(event, this);" onclick="return $$._onTableClick(event, this);" cellspacing="0" cellpadding="0">' + '<tr style="border-bottom: 1px solid #ddd;font-size: 13px;line-height: 25px;color:#39C;padding-top: 2px"><td colspan="10">' + editor.getLang("themeColor") + "</td> </tr>" + '<tr class="edui-colorpicker-tablefirstrow" >';
            for (var i = 0; i < COLORS.length; i++) {
                if (i && i % 10 === 0) {
                    html += "</tr>" + (i == 60 ? '<tr style="border-bottom: 1px solid #ddd;font-size: 13px;line-height: 25px;color:#39C;"><td colspan="10">' + editor.getLang("standardColor") + "</td></tr>" : "") + "<tr" + (i == 60 ? ' class="edui-colorpicker-tablefirstrow"' : "") + ">"
                }
                html += i < 70 ? '<td style="padding: 0 2px;"><a hidefocus title="' + COLORS[i] + '" onclick="return false;" href="javascript:" unselectable="on" class="edui-box edui-colorpicker-colorcell"' + ' data-color="#' + COLORS[i] + '"' + ' style="background-color:#' + COLORS[i] + ";border:solid #ccc;" + (i < 10 || i >= 60 ? "border-width:1px;" : i >= 10 && i < 20 ? "border-width:1px 1px 0 1px;" : "border-width:0 1px 0 1px;") + '"' + "></a></td>" : ""
            }
            html += "</tr></table></div>";
            return html
        }
    })();
    (function() {
        var utils = baidu.editor.utils,
            uiUtils = baidu.editor.ui.uiUtils,
            UIBase = baidu.editor.ui.UIBase;
        var TablePicker = baidu.editor.ui.TablePicker = function(options) {
            this.initOptions(options);
            this.initTablePicker()
        };
        TablePicker.prototype = {
            defaultNumRows: 10,
            defaultNumCols: 10,
            maxNumRows: 20,
            maxNumCols: 20,
            numRows: 10,
            numCols: 10,
            lengthOfCellSide: 22,
            initTablePicker: function() {
                this.initUIBase()
            },
            getHtmlTpl: function() {
                var me = this;
                return '<div id="##" class="edui-tablepicker %%">' + '<div class="edui-tablepicker-body">' + '<div class="edui-infoarea">' + '<span id="##_label" class="edui-label"></span>' + "</div>" + '<div class="edui-pickarea"' + ' onmousemove="$$._onMouseMove(event, this);"' + ' onmouseover="$$._onMouseOver(event, this);"' + ' onmouseout="$$._onMouseOut(event, this);"' + ' onclick="$$._onClick(event, this);"' + ">" + '<div id="##_overlay" class="edui-overlay"></div>' + "</div>" + "</div>" + "</div>"
            },
            _UIBase_render: UIBase.prototype.render,
            render: function(holder) {
                this._UIBase_render(holder);
                this.getDom("label").innerHTML = "0" + this.editor.getLang("t_row") + " x 0" + this.editor.getLang("t_col")
            },
            _track: function(numCols, numRows) {
                var style = this.getDom("overlay").style;
                var sideLen = this.lengthOfCellSide;
                style.width = numCols * sideLen + "px";
                style.height = numRows * sideLen + "px";
                var label = this.getDom("label");
                label.innerHTML = numCols + this.editor.getLang("t_col") + " x " + numRows + this.editor.getLang("t_row");
                this.numCols = numCols;
                this.numRows = numRows
            },
            _onMouseOver: function(evt, el) {
                var rel = evt.relatedTarget || evt.fromElement;
                if (!uiUtils.contains(el, rel) && el !== rel) {
                    this.getDom("label").innerHTML = "0" + this.editor.getLang("t_col") + " x 0" + this.editor.getLang("t_row");
                    this.getDom("overlay").style.visibility = ""
                }
            },
            _onMouseOut: function(evt, el) {
                var rel = evt.relatedTarget || evt.toElement;
                if (!uiUtils.contains(el, rel) && el !== rel) {
                    this.getDom("label").innerHTML = "0" + this.editor.getLang("t_col") + " x 0" + this.editor.getLang("t_row");
                    this.getDom("overlay").style.visibility = "hidden"
                }
            },
            _onMouseMove: function(evt, el) {
                var style = this.getDom("overlay").style;
                var offset = uiUtils.getEventOffset(evt);
                var sideLen = this.lengthOfCellSide;
                var numCols = Math.ceil(offset.left / sideLen);
                var numRows = Math.ceil(offset.top / sideLen);
                this._track(numCols, numRows)
            },
            _onClick: function() {
                this.fireEvent("picktable", this.numCols, this.numRows)
            }
        };
        utils.inherits(TablePicker, UIBase)
    })();
    (function() {
        var browser = baidu.editor.browser,
            domUtils = baidu.editor.dom.domUtils,
            uiUtils = baidu.editor.ui.uiUtils;
        var TPL_STATEFUL = 'onmousedown="$$.Stateful_onMouseDown(event, this);"' + ' onmouseup="$$.Stateful_onMouseUp(event, this);"' + (browser.ie ? (' onmouseenter="$$.Stateful_onMouseEnter(event, this);"' + ' onmouseleave="$$.Stateful_onMouseLeave(event, this);"') : (' onmouseover="$$.Stateful_onMouseOver(event, this);"' + ' onmouseout="$$.Stateful_onMouseOut(event, this);"'));
        baidu.editor.ui.Stateful = {
            alwalysHoverable: false,
            target: null,
            Stateful_init: function() {
                this._Stateful_dGetHtmlTpl = this.getHtmlTpl;
                this.getHtmlTpl = this.Stateful_getHtmlTpl
            },
            Stateful_getHtmlTpl: function() {
                var tpl = this._Stateful_dGetHtmlTpl();
                return tpl.replace(/stateful/g, function() {
                    return TPL_STATEFUL
                })
            },
            Stateful_onMouseEnter: function(evt, el) {
                this.target = el;
                if (!this.isDisabled() || this.alwalysHoverable) {
                    this.addState("hover");
                    this.fireEvent("over")
                }
            },
            Stateful_onMouseLeave: function(evt, el) {
                if (!this.isDisabled() || this.alwalysHoverable) {
                    this.removeState("hover");
                    this.removeState("active");
                    this.fireEvent("out")
                }
            },
            Stateful_onMouseOver: function(evt, el) {
                var rel = evt.relatedTarget;
                if (!uiUtils.contains(el, rel) && el !== rel) {
                    this.Stateful_onMouseEnter(evt, el)
                }
            },
            Stateful_onMouseOut: function(evt, el) {
                var rel = evt.relatedTarget;
                if (!uiUtils.contains(el, rel) && el !== rel) {
                    this.Stateful_onMouseLeave(evt, el)
                }
            },
            Stateful_onMouseDown: function(evt, el) {
                if (!this.isDisabled()) {
                    this.addState("active")
                }
            },
            Stateful_onMouseUp: function(evt, el) {
                if (!this.isDisabled()) {
                    this.removeState("active")
                }
            },
            Stateful_postRender: function() {
                if (this.disabled && !this.hasState("disabled")) {
                    this.addState("disabled")
                }
            },
            hasState: function(state) {
                return domUtils.hasClass(this.getStateDom(), "edui-state-" + state)
            },
            addState: function(state) {
                if (!this.hasState(state)) {
                    this.getStateDom().className += " edui-state-" + state
                }
            },
            removeState: function(state) {
                if (this.hasState(state)) {
                    domUtils.removeClasses(this.getStateDom(), ["edui-state-" + state])
                }
            },
            getStateDom: function() {
                return this.getDom("state")
            },
            isChecked: function() {
                return this.hasState("checked")
            },
            setChecked: function(checked) {
                if (!this.isDisabled() && checked) {
                    this.addState("checked")
                } else {
                    this.removeState("checked")
                }
            },
            isDisabled: function() {
                return this.hasState("disabled")
            },
            setDisabled: function(disabled) {
                if (disabled) {
                    this.removeState("hover");
                    this.removeState("checked");
                    this.removeState("active");
                    this.addState("disabled")
                } else {
                    this.removeState("disabled")
                }
            }
        }
    })();
    (function() {
        var utils = baidu.editor.utils,
            UIBase = baidu.editor.ui.UIBase,
            Stateful = baidu.editor.ui.Stateful,
            Button = baidu.editor.ui.Button = function(options) {
                if (options.name) {
                    var btnName = options.name;
                    var cssRules = options.cssRules;
                    if (!options.className) {
                        options.className = "edui-for-" + btnName
                    }
                    options.cssRules = ".edui-default  .edui-for-" + btnName + " .edui-icon {" + cssRules + "}"
                }
                this.initOptions(options);
                this.initButton()
            };
        Button.prototype = {
            uiName: "button",
            label: "",
            title: "",
            showIcon: true,
            showText: true,
            cssRules: "",
            initButton: function() {
                this.initUIBase();
                this.Stateful_init();
                if (this.cssRules) {
                    utils.cssRule("edui-customize-" + this.name + "-style", this.cssRules)
                }
            },
            getHtmlTpl: function() {
                return '<div id="##" class="edui-box %%">' + '<div id="##_state" stateful>' + '<div class="%%-wrap"><div id="##_body" unselectable="on" ' + (this.title ? 'title="' + this.title + '"' : "") + ' class="%%-body" onmousedown="return $$._onMouseDown(event, this);" onclick="return $$._onClick(event, this);">' + (this.showIcon ? '<div class="edui-box edui-icon"></div>' : "") + (this.showText ? '<div class="edui-box edui-label">' + this.label + "</div>" : "") + "</div>" + "</div>" + "</div></div>"
            },
            postRender: function() {
                this.Stateful_postRender();
                this.setDisabled(this.disabled)
            },
            _onMouseDown: function(e) {
                var target = e.target || e.srcElement,
                    tagName = target && target.tagName && target.tagName.toLowerCase();
                if (tagName == "input" || tagName == "object" || tagName == "object") {
                    return false
                }
            },
            _onClick: function() {
                if (!this.isDisabled()) {
                    this.fireEvent("click")
                }
            },
            setTitle: function(text) {
                var label = this.getDom("label");
                label.innerHTML = text
            }
        };
        utils.inherits(Button, UIBase);
        utils.extend(Button.prototype, Stateful)
    })();
    (function() {
        var utils = baidu.editor.utils,
            uiUtils = baidu.editor.ui.uiUtils,
            domUtils = baidu.editor.dom.domUtils,
            UIBase = baidu.editor.ui.UIBase,
            Stateful = baidu.editor.ui.Stateful,
            SplitButton = baidu.editor.ui.SplitButton = function(options) {
                this.initOptions(options);
                this.initSplitButton()
            };
        SplitButton.prototype = {
            popup: null,
            uiName: "splitbutton",
            title: "",
            initSplitButton: function() {
                this.initUIBase();
                this.Stateful_init();
                var me = this;
                if (this.popup != null) {
                    var popup = this.popup;
                    this.popup = null;
                    this.setPopup(popup)
                }
            },
            _UIBase_postRender: UIBase.prototype.postRender,
            postRender: function() {
                this.Stateful_postRender();
                this._UIBase_postRender()
            },
            setPopup: function(popup) {
                if (this.popup === popup) {
                    return
                }
                if (this.popup != null) {
                    this.popup.dispose()
                }
                popup.addListener("show", utils.bind(this._onPopupShow, this));
                popup.addListener("hide", utils.bind(this._onPopupHide, this));
                popup.addListener("postrender", utils.bind(function() {
                    popup.getDom("body").appendChild(uiUtils.createElementByHtml('<div id="' + this.popup.id + '_bordereraser" class="edui-bordereraser edui-background" style="width:' + (uiUtils.getClientRect(this.getDom()).width + 20) + 'px"></div>'));
                    popup.getDom().className += " " + this.className
                }, this));
                this.popup = popup
            },
            _onPopupShow: function() {
                this.addState("opened")
            },
            _onPopupHide: function() {
                this.removeState("opened")
            },
            getHtmlTpl: function() {
                return '<div id="##" class="edui-box %%">' + "<div " + (this.title ? 'title="' + this.title + '"' : "") + ' id="##_state" stateful><div class="%%-body">' + '<div id="##_button_body" class="edui-box edui-button-body" onclick="$$._onButtonClick(event, this);">' + '<div class="edui-box edui-icon"></div>' + "</div>" + '<div class="edui-box edui-splitborder"></div>' + '<div class="edui-box edui-arrow" onclick="$$._onArrowClick();"></div>' + "</div></div></div>"
            },
            showPopup: function() {
                var rect = uiUtils.getClientRect(this.getDom());
                rect.top -= this.popup.SHADOW_RADIUS;
                rect.height += this.popup.SHADOW_RADIUS;
                this.popup.showAnchorRect(rect)
            },
            _onArrowClick: function(event, el) {
                if (!this.isDisabled()) {
                    this.showPopup()
                }
            },
            _onButtonClick: function() {
                if (!this.isDisabled()) {
                    this.fireEvent("buttonclick")
                }
            }
        };
        utils.inherits(SplitButton, UIBase);
        utils.extend(SplitButton.prototype, Stateful, true)
    })();
    (function() {
        var utils = baidu.editor.utils,
            uiUtils = baidu.editor.ui.uiUtils,
            ColorPicker = baidu.editor.ui.ColorPicker,
            Popup = baidu.editor.ui.Popup,
            SplitButton = baidu.editor.ui.SplitButton,
            ColorButton = baidu.editor.ui.ColorButton = function(options) {
                this.initOptions(options);
                this.initColorButton()
            };
        ColorButton.prototype = {
            initColorButton: function() {
                var me = this;
                this.popup = new Popup({
                    content: new ColorPicker({
                        noColorText: me.editor.getLang("clearColor"),
                        editor: me.editor,
                        onpickcolor: function(t, color) {
                            me._onPickColor(color)
                        },
                        onpicknocolor: function(t, color) {
                            me._onPickNoColor(color)
                        }
                    }),
                    editor: me.editor
                });
                this.initSplitButton()
            },
            _SplitButton_postRender: SplitButton.prototype.postRender,
            postRender: function() {
                this._SplitButton_postRender();
                this.getDom("button_body").appendChild(uiUtils.createElementByHtml('<div id="' + this.id + '_colorlump" class="edui-colorlump"></div>'));
                this.getDom().className += " edui-colorbutton"
            },
            setColor: function(color) {
                this.getDom("colorlump").style.backgroundColor = color;
                this.color = color
            },
            _onPickColor: function(color) {
                if (this.fireEvent("pickcolor", color) !== false) {
                    this.setColor(color);
                    this.popup.hide()
                }
            },
            _onPickNoColor: function(color) {
                if (this.fireEvent("picknocolor") !== false) {
                    this.popup.hide()
                }
            }
        };
        utils.inherits(ColorButton, SplitButton)
    })();
    (function() {
        var utils = baidu.editor.utils,
            Popup = baidu.editor.ui.Popup,
            TablePicker = baidu.editor.ui.TablePicker,
            SplitButton = baidu.editor.ui.SplitButton,
            TableButton = baidu.editor.ui.TableButton = function(options) {
                this.initOptions(options);
                this.initTableButton()
            };
        TableButton.prototype = {
            initTableButton: function() {
                var me = this;
                this.popup = new Popup({
                    content: new TablePicker({
                        editor: me.editor,
                        onpicktable: function(t, numCols, numRows) {
                            me._onPickTable(numCols, numRows)
                        }
                    }),
                    "editor": me.editor
                });
                this.initSplitButton()
            },
            _onPickTable: function(numCols, numRows) {
                if (this.fireEvent("picktable", numCols, numRows) !== false) {
                    this.popup.hide()
                }
            }
        };
        utils.inherits(TableButton, SplitButton)
    })();
    (function() {
        var utils = baidu.editor.utils,
            UIBase = baidu.editor.ui.UIBase;
        var AutoTypeSetPicker = baidu.editor.ui.AutoTypeSetPicker = function(options) {
            this.initOptions(options);
            this.initAutoTypeSetPicker()
        };
        AutoTypeSetPicker.prototype = {
            initAutoTypeSetPicker: function() {
                this.initUIBase()
            },
            getHtmlTpl: function() {
                var me = this.editor,
                    opt = me.options.autotypeset,
                    lang = me.getLang("autoTypeSet");
                var textAlignInputName = "textAlignValue" + me.uid,
                    imageBlockInputName = "imageBlockLineValue" + me.uid,
                    symbolConverInputName = "symbolConverValue" + me.uid;
                return '<div id="##" class="edui-autotypesetpicker %%">' + '<div class="edui-autotypesetpicker-body">' + "<table >" + '<tr><td nowrap><input type="checkbox" name="mergeEmptyline" ' + (opt["mergeEmptyline"] ? "checked" : "") + ">" + lang.mergeLine + '</td><td colspan="2"><input type="checkbox" name="removeEmptyline" ' + (opt["removeEmptyline"] ? "checked" : "") + ">" + lang.delLine + "</td></tr>" + '<tr><td nowrap><input type="checkbox" name="removeClass" ' + (opt["removeClass"] ? "checked" : "") + ">" + lang.removeFormat + '</td><td colspan="2"><input type="checkbox" name="indent" ' + (opt["indent"] ? "checked" : "") + ">" + lang.indent + "</td></tr>" + "<tr>" + '<td nowrap><input type="checkbox" name="textAlign" ' + (opt["textAlign"] ? "checked" : "") + ">" + lang.alignment + "</td>" + '<td colspan="2" id="' + textAlignInputName + '">' + '<input type="radio" name="' + textAlignInputName + '" value="left" ' + ((opt["textAlign"] && opt["textAlign"] == "left") ? "checked" : "") + ">" + me.getLang("justifyleft") + '<input type="radio" name="' + textAlignInputName + '" value="center" ' + ((opt["textAlign"] && opt["textAlign"] == "center") ? "checked" : "") + ">" + me.getLang("justifycenter") + '<input type="radio" name="' + textAlignInputName + '" value="right" ' + ((opt["textAlign"] && opt["textAlign"] == "right") ? "checked" : "") + ">" + me.getLang("justifyright") + "</td>" + "</tr>" + "<tr>" + '<td nowrap><input type="checkbox" name="imageBlockLine" ' + (opt["imageBlockLine"] ? "checked" : "") + ">" + lang.imageFloat + "</td>" + '<td nowrap id="' + imageBlockInputName + '">' + '<input type="radio" name="' + imageBlockInputName + '" value="none" ' + ((opt["imageBlockLine"] && opt["imageBlockLine"] == "none") ? "checked" : "") + ">" + me.getLang("default") + '<input type="radio" name="' + imageBlockInputName + '" value="left" ' + ((opt["imageBlockLine"] && opt["imageBlockLine"] == "left") ? "checked" : "") + ">" + me.getLang("justifyleft") + '<input type="radio" name="' + imageBlockInputName + '" value="center" ' + ((opt["imageBlockLine"] && opt["imageBlockLine"] == "center") ? "checked" : "") + ">" + me.getLang("justifycenter") + '<input type="radio" name="' + imageBlockInputName + '" value="right" ' + ((opt["imageBlockLine"] && opt["imageBlockLine"] == "right") ? "checked" : "") + ">" + me.getLang("justifyright") + "</td>" + "</tr>" + '<tr><td nowrap><input type="checkbox" name="clearFontSize" ' + (opt["clearFontSize"] ? "checked" : "") + ">" + lang.removeFontsize + '</td><td colspan="2"><input type="checkbox" name="clearFontFamily" ' + (opt["clearFontFamily"] ? "checked" : "") + ">" + lang.removeFontFamily + "</td></tr>" + '<tr><td nowrap colspan="3"><input type="checkbox" name="removeEmptyNode" ' + (opt["removeEmptyNode"] ? "checked" : "") + ">" + lang.removeHtml + "</td></tr>" + '<tr><td nowrap colspan="3"><input type="checkbox" name="pasteFilter" ' + (opt["pasteFilter"] ? "checked" : "") + ">" + lang.pasteFilter + "</td></tr>" + "<tr>" + '<td nowrap><input type="checkbox" name="symbolConver" ' + (opt["bdc2sb"] || opt["tobdc"] ? "checked" : "") + ">" + lang.symbol + "</td>" + '<td id="' + symbolConverInputName + '">' + '<input type="radio" name="bdc" value="bdc2sb" ' + (opt["bdc2sb"] ? "checked" : "") + ">" + lang.bdc2sb + '<input type="radio" name="bdc" value="tobdc" ' + (opt["tobdc"] ? "checked" : "") + ">" + lang.tobdc + "" + "</td>" + '<td nowrap align="right"><button >' + lang.run + "</button></td>" + "</tr>" + "</table>" + "</div>" + "</div>"
            },
            _UIBase_render: UIBase.prototype.render
        };
        utils.inherits(AutoTypeSetPicker, UIBase)
    })();
    (function() {
        var utils = baidu.editor.utils,
            Popup = baidu.editor.ui.Popup,
            AutoTypeSetPicker = baidu.editor.ui.AutoTypeSetPicker,
            SplitButton = baidu.editor.ui.SplitButton,
            AutoTypeSetButton = baidu.editor.ui.AutoTypeSetButton = function(options) {
                this.initOptions(options);
                this.initAutoTypeSetButton()
            };

        function getPara(me) {
            var opt = {},
                cont = me.getDom(),
                editorId = me.editor.uid,
                inputType = null,
                attrName = null,
                ipts = domUtils.getElementsByTagName(cont, "input");
            for (var i = ipts.length - 1, ipt; ipt = ipts[i--];) {
                inputType = ipt.getAttribute("type");
                if (inputType == "checkbox") {
                    attrName = ipt.getAttribute("name");
                    opt[attrName] && delete opt[attrName];
                    if (ipt.checked) {
                        var attrValue = document.getElementById(attrName + "Value" + editorId);
                        if (attrValue) {
                            if (/input/ig.test(attrValue.tagName)) {
                                opt[attrName] = attrValue.value
                            } else {
                                var iptChilds = attrValue.getElementsByTagName("input");
                                for (var j = iptChilds.length - 1, iptchild; iptchild = iptChilds[j--];) {
                                    if (iptchild.checked) {
                                        opt[attrName] = iptchild.value;
                                        break
                                    }
                                }
                            }
                        } else {
                            opt[attrName] = true
                        }
                    } else {
                        opt[attrName] = false
                    }
                } else {
                    opt[ipt.getAttribute("value")] = ipt.checked
                }
            }
            var selects = domUtils.getElementsByTagName(cont, "select");
            for (var i = 0, si; si = selects[i++];) {
                var attr = si.getAttribute("name");
                opt[attr] = opt[attr] ? si.value : ""
            }
            utils.extend(me.editor.options.autotypeset, opt);
            me.editor.setPreferences("autotypeset", opt)
        }
        AutoTypeSetButton.prototype = {
            initAutoTypeSetButton: function() {
                var me = this;
                this.popup = new Popup({
                    content: new AutoTypeSetPicker({
                        editor: me.editor
                    }),
                    "editor": me.editor,
                    hide: function() {
                        if (!this._hidden && this.getDom()) {
                            getPara(this);
                            this.getDom().style.display = "none";
                            this._hidden = true;
                            this.fireEvent("hide")
                        }
                    }
                });
                var flag = 0;
                this.popup.addListener("postRenderAfter", function() {
                    var popupUI = this;
                    if (flag) {
                        return
                    }
                    var cont = this.getDom(),
                        btn = cont.getElementsByTagName("button")[0];
                    btn.onclick = function() {
                        getPara(popupUI);
                        me.editor.execCommand("autotypeset");
                        popupUI.hide()
                    };
                    domUtils.on(cont, "click", function(e) {
                        var target = e.target || e.srcElement,
                            editorId = me.editor.uid;
                        if (target && target.tagName == "INPUT") {
                            if (target.name == "imageBlockLine" || target.name == "textAlign" || target.name == "symbolConver") {
                                var checked = target.checked,
                                    radioTd = document.getElementById(target.name + "Value" + editorId),
                                    radios = radioTd.getElementsByTagName("input"),
                                    defalutSelect = {
                                        "imageBlockLine": "none",
                                        "textAlign": "left",
                                        "symbolConver": "tobdc"
                                    };
                                for (var i = 0; i < radios.length; i++) {
                                    if (checked) {
                                        if (radios[i].value == defalutSelect[target.name]) {
                                            radios[i].checked = "checked"
                                        }
                                    } else {
                                        radios[i].checked = false
                                    }
                                }
                            }
                            if (target.name == ("imageBlockLineValue" + editorId) || target.name == ("textAlignValue" + editorId) || target.name == "bdc") {
                                var checkboxs = target.parentNode.previousSibling.getElementsByTagName("input");
                                checkboxs && (checkboxs[0].checked = true)
                            }
                            getPara(popupUI)
                        }
                    });
                    flag = 1
                });
                this.initSplitButton()
            }
        };
        utils.inherits(AutoTypeSetButton, SplitButton)
    })();
    (function() {
        var utils = baidu.editor.utils,
            Popup = baidu.editor.ui.Popup,
            Stateful = baidu.editor.ui.Stateful,
            UIBase = baidu.editor.ui.UIBase;
        var CellAlignPicker = baidu.editor.ui.CellAlignPicker = function(options) {
            this.initOptions(options);
            this.initSelected();
            this.initCellAlignPicker()
        };
        CellAlignPicker.prototype = {
            initSelected: function() {
                var status = {
                        valign: {
                            top: 0,
                            middle: 1,
                            bottom: 2
                        },
                        align: {
                            left: 0,
                            center: 1,
                            right: 2
                        },
                        count: 3
                    },
                    result = -1;
                if (this.selected) {
                    this.selectedIndex = status.valign[this.selected.valign] * status.count + status.align[this.selected.align]
                }
            },
            initCellAlignPicker: function() {
                this.initUIBase();
                this.Stateful_init()
            },
            getHtmlTpl: function() {
                var alignType = ["left", "center", "right"],
                    COUNT = 9,
                    tempClassName = null,
                    tempIndex = -1,
                    tmpl = [];
                for (var i = 0; i < COUNT; i++) {
                    tempClassName = this.selectedIndex === i ? ' class="edui-cellalign-selected" ' : "";
                    tempIndex = i % 3;
                    tempIndex === 0 && tmpl.push("<tr>");
                    tmpl.push('<td index="' + i + '" ' + tempClassName + ' stateful><div class="edui-icon edui-' + alignType[tempIndex] + '"></div></td>');
                    tempIndex === 2 && tmpl.push("</tr>")
                }
                return '<div id="##" class="edui-cellalignpicker %%">' + '<div class="edui-cellalignpicker-body">' + '<table onclick="$$._onClick(event);">' + tmpl.join("") + "</table>" + "</div>" + "</div>"
            },
            getStateDom: function() {
                return this.target
            },
            _onClick: function(evt) {
                var target = evt.target || evt.srcElement;
                if (/icon/.test(target.className)) {
                    this.items[target.parentNode.getAttribute("index")].onclick();
                    Popup.postHide(evt)
                }
            },
            _UIBase_render: UIBase.prototype.render
        };
        utils.inherits(CellAlignPicker, UIBase);
        utils.extend(CellAlignPicker.prototype, Stateful, true)
    })();
    (function() {
        var utils = baidu.editor.utils,
            Stateful = baidu.editor.ui.Stateful,
            uiUtils = baidu.editor.ui.uiUtils,
            UIBase = baidu.editor.ui.UIBase;
        var PastePicker = baidu.editor.ui.PastePicker = function(options) {
            this.initOptions(options);
            this.initPastePicker()
        };
        PastePicker.prototype = {
            initPastePicker: function() {
                this.initUIBase();
                this.Stateful_init()
            },
            getHtmlTpl: function() {
                return '<div class="edui-pasteicon" onclick="$$._onClick(this)"></div>' + '<div class="edui-pastecontainer">' + '<div class="edui-title">' + this.editor.getLang("pasteOpt") + "</div>" + '<div class="edui-button">' + '<div title="' + this.editor.getLang("pasteSourceFormat") + '" onclick="$$.format(false)" stateful>' + '<div class="edui-richtxticon"></div></div>' + '<div title="' + this.editor.getLang("tagFormat") + '" onclick="$$.format(2)" stateful>' + '<div class="edui-tagicon"></div></div>' + '<div title="' + this.editor.getLang("pasteTextFormat") + '" onclick="$$.format(true)" stateful>' + '<div class="edui-plaintxticon"></div></div>' + "</div>" + "</div>" + "</div>"
            },
            getStateDom: function() {
                return this.target
            },
            format: function(param) {
                this.editor.ui._isTransfer = true;
                this.editor.fireEvent("pasteTransfer", param)
            },
            _onClick: function(cur) {
                var node = domUtils.getNextDomNode(cur),
                    screenHt = uiUtils.getViewportRect().height,
                    subPop = uiUtils.getClientRect(node);
                if ((subPop.top + subPop.height) > screenHt) {
                    node.style.top = (-subPop.height - cur.offsetHeight) + "px"
                } else {
                    node.style.top = ""
                }
                if (/hidden/ig.test(domUtils.getComputedStyle(node, "visibility"))) {
                    node.style.visibility = "visible";
                    domUtils.addClass(cur, "edui-state-opened")
                } else {
                    node.style.visibility = "hidden";
                    domUtils.removeClasses(cur, "edui-state-opened")
                }
            },
            _UIBase_render: UIBase.prototype.render
        };
        utils.inherits(PastePicker, UIBase);
        utils.extend(PastePicker.prototype, Stateful, true)
    })();
    (function() {
        var utils = baidu.editor.utils,
            uiUtils = baidu.editor.ui.uiUtils,
            UIBase = baidu.editor.ui.UIBase,
            Toolbar = baidu.editor.ui.Toolbar = function(options) {
                this.initOptions(options);
                this.initToolbar()
            };
        Toolbar.prototype = {
            items: null,
            initToolbar: function() {
                this.items = this.items || [];
                this.initUIBase()
            },
            add: function(item, index) {
                if (index === undefined) {
                    this.items.push(item)
                } else {
                    this.items.splice(index, 0, item)
                }
            },
            getHtmlTpl: function() {
                var buff = [];
                for (var i = 0; i < this.items.length; i++) {
                    buff[i] = this.items[i].renderHtml()
                }
                return '<div id="##" class="edui-toolbar %%" onselectstart="return false;" onmousedown="return $$._onMouseDown(event, this);">' + buff.join("") + "</div>"
            },
            postRender: function() {
                var box = this.getDom();
                for (var i = 0; i < this.items.length; i++) {
                    this.items[i].postRender()
                }
                uiUtils.makeUnselectable(box)
            },
            _onMouseDown: function(e) {
                var target = e.target || e.srcElement,
                    tagName = target && target.tagName && target.tagName.toLowerCase();
                if (tagName == "input" || tagName == "object" || tagName == "object") {
                    return false
                }
            }
        };
        utils.inherits(Toolbar, UIBase)
    })();
    (function() {
        var utils = baidu.editor.utils,
            domUtils = baidu.editor.dom.domUtils,
            uiUtils = baidu.editor.ui.uiUtils,
            UIBase = baidu.editor.ui.UIBase,
            Popup = baidu.editor.ui.Popup,
            Stateful = baidu.editor.ui.Stateful,
            CellAlignPicker = baidu.editor.ui.CellAlignPicker,
            Menu = baidu.editor.ui.Menu = function(options) {
                this.initOptions(options);
                this.initMenu()
            };
        var menuSeparator = {
            renderHtml: function() {
                return '<div class="edui-menuitem edui-menuseparator"><div class="edui-menuseparator-inner"></div></div>'
            },
            postRender: function() {},
            queryAutoHide: function() {
                return true
            }
        };
        Menu.prototype = {
            items: null,
            uiName: "menu",
            initMenu: function() {
                this.items = this.items || [];
                this.initPopup();
                this.initItems()
            },
            initItems: function() {
                for (var i = 0; i < this.items.length; i++) {
                    var item = this.items[i];
                    if (item == "-") {
                        this.items[i] = this.getSeparator()
                    } else {
                        if (!(item instanceof MenuItem)) {
                            item.editor = this.editor;
                            item.theme = this.editor.options.theme;
                            this.items[i] = this.createItem(item)
                        }
                    }
                }
            },
            getSeparator: function() {
                return menuSeparator
            },
            createItem: function(item) {
                item.menu = this;
                return new MenuItem(item)
            },
            _Popup_getContentHtmlTpl: Popup.prototype.getContentHtmlTpl,
            getContentHtmlTpl: function() {
                if (this.items.length == 0) {
                    return this._Popup_getContentHtmlTpl()
                }
                var buff = [];
                for (var i = 0; i < this.items.length; i++) {
                    var item = this.items[i];
                    buff[i] = item.renderHtml()
                }
                return ('<div class="%%-body">' + buff.join("") + "</div>")
            },
            _Popup_postRender: Popup.prototype.postRender,
            postRender: function() {
                var me = this;
                for (var i = 0; i < this.items.length; i++) {
                    var item = this.items[i];
                    item.ownerMenu = this;
                    item.postRender()
                }
                domUtils.on(this.getDom(), "mouseover", function(evt) {
                    evt = evt || event;
                    var rel = evt.relatedTarget || evt.fromElement;
                    var el = me.getDom();
                    if (!uiUtils.contains(el, rel) && el !== rel) {
                        me.fireEvent("over")
                    }
                });
                this._Popup_postRender()
            },
            queryAutoHide: function(el) {
                if (el) {
                    if (uiUtils.contains(this.getDom(), el)) {
                        return false
                    }
                    for (var i = 0; i < this.items.length; i++) {
                        var item = this.items[i];
                        if (item.queryAutoHide(el) === false) {
                            return false
                        }
                    }
                }
            },
            clearItems: function() {
                for (var i = 0; i < this.items.length; i++) {
                    var item = this.items[i];
                    clearTimeout(item._showingTimer);
                    clearTimeout(item._closingTimer);
                    if (item.subMenu) {
                        item.subMenu.destroy()
                    }
                }
                this.items = []
            },
            destroy: function() {
                if (this.getDom()) {
                    domUtils.remove(this.getDom())
                }
                this.clearItems()
            },
            dispose: function() {
                this.destroy()
            }
        };
        utils.inherits(Menu, Popup);
        var MenuItem = baidu.editor.ui.MenuItem = function(options) {
            this.initOptions(options);
            this.initUIBase();
            this.Stateful_init();
            if (this.subMenu && !(this.subMenu instanceof Menu)) {
                if (options.className && options.className.indexOf("aligntd") != -1) {
                    var me = this;
                    this.subMenu.selected = this.editor.queryCommandValue("cellalignment");
                    this.subMenu = new Popup({
                        content: new CellAlignPicker(this.subMenu),
                        parentMenu: me,
                        editor: me.editor,
                        destroy: function() {
                            if (this.getDom()) {
                                domUtils.remove(this.getDom())
                            }
                        }
                    });
                    this.subMenu.addListener("postRenderAfter", function() {
                        domUtils.on(this.getDom(), "mouseover", function() {
                            me.addState("opened")
                        })
                    })
                } else {
                    this.subMenu = new Menu(this.subMenu)
                }
            }
        };
        MenuItem.prototype = {
            label: "",
            subMenu: null,
            ownerMenu: null,
            uiName: "menuitem",
            alwalysHoverable: true,
            getHtmlTpl: function() {
                return '<div id="##" class="%%" stateful onclick="$$._onClick(event, this);">' + '<div class="%%-body">' + this.renderLabelHtml() + "</div>" + "</div>"
            },
            postRender: function() {
                var me = this;
                this.addListener("over", function() {
                    me.ownerMenu.fireEvent("submenuover", me);
                    if (me.subMenu) {
                        me.delayShowSubMenu()
                    }
                });
                if (this.subMenu) {
                    this.getDom().className += " edui-hassubmenu";
                    this.subMenu.render();
                    this.addListener("out", function() {
                        me.delayHideSubMenu()
                    });
                    this.subMenu.addListener("over", function() {
                        clearTimeout(me._closingTimer);
                        me._closingTimer = null;
                        me.addState("opened")
                    });
                    this.ownerMenu.addListener("hide", function() {
                        me.hideSubMenu()
                    });
                    this.ownerMenu.addListener("submenuover", function(t, subMenu) {
                        if (subMenu !== me) {
                            me.delayHideSubMenu()
                        }
                    });
                    this.subMenu._bakQueryAutoHide = this.subMenu.queryAutoHide;
                    this.subMenu.queryAutoHide = function(el) {
                        if (el && uiUtils.contains(me.getDom(), el)) {
                            return false
                        }
                        return this._bakQueryAutoHide(el)
                    }
                }
                this.getDom().style.tabIndex = "-1";
                uiUtils.makeUnselectable(this.getDom());
                this.Stateful_postRender()
            },
            delayShowSubMenu: function() {
                var me = this;
                if (!me.isDisabled()) {
                    me.addState("opened");
                    clearTimeout(me._showingTimer);
                    clearTimeout(me._closingTimer);
                    me._closingTimer = null;
                    me._showingTimer = setTimeout(function() {
                        me.showSubMenu()
                    }, 250)
                }
            },
            delayHideSubMenu: function() {
                var me = this;
                if (!me.isDisabled()) {
                    me.removeState("opened");
                    clearTimeout(me._showingTimer);
                    if (!me._closingTimer) {
                        me._closingTimer = setTimeout(function() {
                            if (!me.hasState("opened")) {
                                me.hideSubMenu()
                            }
                            me._closingTimer = null
                        }, 400)
                    }
                }
            },
            renderLabelHtml: function() {
                return '<div class="edui-arrow"></div>' + '<div class="edui-box edui-icon"></div>' + '<div class="edui-box edui-label %%-label">' + (this.label || "") + "</div>"
            },
            getStateDom: function() {
                return this.getDom()
            },
            queryAutoHide: function(el) {
                if (this.subMenu && this.hasState("opened")) {
                    return this.subMenu.queryAutoHide(el)
                }
            },
            _onClick: function(event, this_) {
                if (this.hasState("disabled")) {
                    return
                }
                if (this.fireEvent("click", event, this_) !== false) {
                    if (this.subMenu) {
                        this.showSubMenu()
                    } else {
                        Popup.postHide(event)
                    }
                }
            },
            showSubMenu: function() {
                var rect = uiUtils.getClientRect(this.getDom());
                rect.right -= 5;
                rect.left += 2;
                rect.width -= 7;
                rect.top -= 4;
                rect.bottom += 4;
                rect.height += 8;
                this.subMenu.showAnchorRect(rect, true, true)
            },
            hideSubMenu: function() {
                this.subMenu.hide()
            }
        };
        utils.inherits(MenuItem, UIBase);
        utils.extend(MenuItem.prototype, Stateful, true)
    })();
    (function() {
        var utils = baidu.editor.utils,
            uiUtils = baidu.editor.ui.uiUtils,
            Menu = baidu.editor.ui.Menu,
            SplitButton = baidu.editor.ui.SplitButton,
            Combox = baidu.editor.ui.Combox = function(options) {
                this.initOptions(options);
                this.initCombox()
            };
        Combox.prototype = {
            uiName: "combox",
            onbuttonclick: function() {
                this.showPopup()
            },
            initCombox: function() {
                var me = this;
                this.items = this.items || [];
                for (var i = 0; i < this.items.length; i++) {
                    var item = this.items[i];
                    item.uiName = "listitem";
                    item.index = i;
                    item.onclick = function() {
                        me.selectByIndex(this.index)
                    }
                }
                this.popup = new Menu({
                    items: this.items,
                    uiName: "list",
                    editor: this.editor,
                    captureWheel: true,
                    combox: this
                });
                this.initSplitButton()
            },
            _SplitButton_postRender: SplitButton.prototype.postRender,
            postRender: function() {
                this._SplitButton_postRender();
                this.setLabel(this.label || "");
                this.setValue(this.initValue || "")
            },
            showPopup: function() {
                var rect = uiUtils.getClientRect(this.getDom());
                rect.top += 1;
                rect.bottom -= 1;
                rect.height -= 2;
                this.popup.showAnchorRect(rect)
            },
            getValue: function() {
                return this.value
            },
            setValue: function(value) {
                var index = this.indexByValue(value);
                if (index != -1) {
                    this.selectedIndex = index;
                    this.setLabel(this.items[index].label);
                    this.value = this.items[index].value
                } else {
                    this.selectedIndex = -1;
                    this.setLabel(this.getLabelForUnknowValue(value));
                    this.value = value
                }
            },
            setLabel: function(label) {
                this.getDom("button_body").innerHTML = label;
                this.label = label
            },
            getLabelForUnknowValue: function(value) {
                return value
            },
            indexByValue: function(value) {
                for (var i = 0; i < this.items.length; i++) {
                    if (value == this.items[i].value) {
                        return i
                    }
                }
                return -1
            },
            getItem: function(index) {
                return this.items[index]
            },
            selectByIndex: function(index) {
                if (index < this.items.length && this.fireEvent("select", index) !== false) {
                    this.selectedIndex = index;
                    this.value = this.items[index].value;
                    this.setLabel(this.items[index].label)
                }
            }
        };
        utils.inherits(Combox, SplitButton)
    })();
    (function() {
        var utils = baidu.editor.utils,
            domUtils = baidu.editor.dom.domUtils,
            uiUtils = baidu.editor.ui.uiUtils,
            Mask = baidu.editor.ui.Mask,
            UIBase = baidu.editor.ui.UIBase,
            Button = baidu.editor.ui.Button,
            Dialog = baidu.editor.ui.Dialog = function(options) {
                if (options.name) {
                    var name = options.name;
                    var cssRules = options.cssRules;
                    if (!options.className) {
                        options.className = "edui-for-" + name
                    }
                    if (cssRules) {
                        options.cssRules = ".edui-default .edui-for-" + name + " .edui-dialog-content  {" + cssRules + "}"
                    }
                }
                this.initOptions(utils.extend({
                    autoReset: true,
                    draggable: true,
                    onok: function() {},
                    oncancel: function() {},
                    onclose: function(t, ok) {
                        return ok ? this.onok() : this.oncancel()
                    },
                    holdScroll: false
                }, options));
                this.initDialog()
            };
        var modalMask;
        var dragMask;
        var activeDialog;
        Dialog.prototype = {
            draggable: false,
            uiName: "dialog",
            initDialog: function() {
                var me = this,
                    theme = this.editor.options.theme;
                if (this.cssRules) {
                    utils.cssRule("edui-customize-" + this.name + "-style", this.cssRules)
                }
                this.initUIBase();
                this.modalMask = (modalMask || (modalMask = new Mask({
                    className: "edui-dialog-modalmask",
                    theme: theme,
                    onclick: function() {
                        activeDialog && activeDialog.close(false)
                    }
                })));
                this.dragMask = (dragMask || (dragMask = new Mask({
                    className: "edui-dialog-dragmask",
                    theme: theme
                })));
                this.closeButton = new Button({
                    className: "edui-dialog-closebutton",
                    title: me.closeDialog,
                    theme: theme,
                    onclick: function() {
                        me.close(false)
                    }
                });
                this.fullscreen && this.initResizeEvent();
                if (this.buttons) {
                    for (var i = 0; i < this.buttons.length; i++) {
                        if (!(this.buttons[i] instanceof Button)) {
                            this.buttons[i] = new Button(utils.extend(this.buttons[i], {
                                editor: this.editor
                            }, true))
                        }
                    }
                }
            },
            initResizeEvent: function() {
                var me = this;
                domUtils.on(window, "resize", function() {
                    if (me._hidden || me._hidden === undefined) {
                        return
                    }
                    if (me.__resizeTimer) {
                        window.clearTimeout(me.__resizeTimer)
                    }
                    me.__resizeTimer = window.setTimeout(function() {
                        me.__resizeTimer = null;
                        var dialogWrapNode = me.getDom(),
                            contentNode = me.getDom("content"),
                            wrapRect = UE.ui.uiUtils.getClientRect(dialogWrapNode),
                            contentRect = UE.ui.uiUtils.getClientRect(contentNode),
                            vpRect = uiUtils.getViewportRect();
                        contentNode.style.width = (vpRect.width - wrapRect.width + contentRect.width) + "px";
                        contentNode.style.height = (vpRect.height - wrapRect.height + contentRect.height) + "px";
                        dialogWrapNode.style.width = vpRect.width + "px";
                        dialogWrapNode.style.height = vpRect.height + "px";
                        me.fireEvent("resize")
                    }, 100)
                })
            },
            fitSize: function() {
                var popBodyEl = this.getDom("body");
                var size = this.mesureSize();
                popBodyEl.style.width = size.width + "px";
                popBodyEl.style.height = size.height + "px";
                return size
            },
            safeSetOffset: function(offset) {
                var me = this;
                var el = me.getDom();
                var vpRect = uiUtils.getViewportRect();
                var rect = uiUtils.getClientRect(el);
                var left = offset.left;
                if (left + rect.width > vpRect.right) {
                    left = vpRect.right - rect.width
                }
                var top = offset.top;
                if (top + rect.height > vpRect.bottom) {
                    top = vpRect.bottom - rect.height
                }
                el.style.left = Math.max(left, 0) + "px";
                el.style.top = Math.max(top, 0) + "px"
            },
            showAtCenter: function() {
                var vpRect = uiUtils.getViewportRect();
                if (!this.fullscreen) {
                    this.getDom().style.display = "";
                    var popSize = this.fitSize();
                    var titleHeight = this.getDom("titlebar").offsetHeight | 0;
                    var left = vpRect.width / 2 - popSize.width / 2;
                    var top = vpRect.height / 2 - (popSize.height - titleHeight) / 2 - titleHeight;
                    var popEl = this.getDom();
                    this.safeSetOffset({
                        left: Math.max(left | 0, 0),
                        top: Math.max(top | 0, 0)
                    });
                    if (!domUtils.hasClass(popEl, "edui-state-centered")) {
                        popEl.className += " edui-state-centered"
                    }
                } else {
                    var dialogWrapNode = this.getDom(),
                        contentNode = this.getDom("content");
                    dialogWrapNode.style.display = "block";
                    var wrapRect = UE.ui.uiUtils.getClientRect(dialogWrapNode),
                        contentRect = UE.ui.uiUtils.getClientRect(contentNode);
                    dialogWrapNode.style.left = "-100000px";
                    contentNode.style.width = (vpRect.width - wrapRect.width + contentRect.width) + "px";
                    contentNode.style.height = (vpRect.height - wrapRect.height + contentRect.height) + "px";
                    dialogWrapNode.style.width = vpRect.width + "px";
                    dialogWrapNode.style.height = vpRect.height + "px";
                    dialogWrapNode.style.left = 0;
                    this._originalContext = {
                        html: {
                            overflowX: document.documentElement.style.overflowX,
                            overflowY: document.documentElement.style.overflowY
                        },
                        body: {
                            overflowX: document.body.style.overflowX,
                            overflowY: document.body.style.overflowY
                        }
                    };
                    document.documentElement.style.overflowX = "hidden";
                    document.documentElement.style.overflowY = "hidden";
                    document.body.style.overflowX = "hidden";
                    document.body.style.overflowY = "hidden"
                }
                this._show()
            },
            getContentHtml: function() {
                var contentHtml = "";
                if (typeof this.content == "string") {
                    contentHtml = this.content
                } else {
                    if (this.iframeUrl) {
                        contentHtml = '<span id="' + this.id + '_contmask" class="dialogcontmask"></span><iframe id="' + this.id + '_iframe" class="%%-iframe" height="100%" width="100%" frameborder="0" src="' + this.iframeUrl + '"></iframe>'
                    }
                }
                return contentHtml
            },
            getHtmlTpl: function() {
                var footHtml = "";
                if (this.buttons) {
                    var buff = [];
                    for (var i = 0; i < this.buttons.length; i++) {
                        buff[i] = this.buttons[i].renderHtml()
                    }
                    footHtml = '<div class="%%-foot">' + '<div id="##_buttons" class="%%-buttons">' + buff.join("") + "</div>" + "</div>"
                }
                return '<div id="##" class="%%"><div ' + (!this.fullscreen ? 'class="%%"' : 'class="%%-wrap edui-dialog-fullscreen-flag"') + '><div id="##_body" class="%%-body">' + '<div class="%%-shadow"></div>' + '<div id="##_titlebar" class="%%-titlebar">' + '<div class="%%-draghandle" onmousedown="$$._onTitlebarMouseDown(event, this);">' + '<span class="%%-caption">' + (this.title || "") + "</span>" + "</div>" + this.closeButton.renderHtml() + "</div>" + '<div id="##_content" class="%%-content">' + (this.autoReset ? "" : this.getContentHtml()) + "</div>" + footHtml + "</div></div></div>"
            },
            postRender: function() {
                if (!this.modalMask.getDom()) {
                    this.modalMask.render();
                    this.modalMask.hide()
                }
                if (!this.dragMask.getDom()) {
                    this.dragMask.render();
                    this.dragMask.hide()
                }
                var me = this;
                this.addListener("show", function() {
                    me.modalMask.show(this.getDom().style.zIndex - 2)
                });
                this.addListener("hide", function() {
                    me.modalMask.hide()
                });
                if (this.buttons) {
                    for (var i = 0; i < this.buttons.length; i++) {
                        this.buttons[i].postRender()
                    }
                }
                domUtils.on(window, "resize", function() {
                    setTimeout(function() {
                        if (!me.isHidden()) {
                            me.safeSetOffset(uiUtils.getClientRect(me.getDom()))
                        }
                    })
                });
                this._hide()
            },
            mesureSize: function() {
                var body = this.getDom("body");
                var width = uiUtils.getClientRect(this.getDom("content")).width;
                var dialogBodyStyle = body.style;
                dialogBodyStyle.width = width;
                return uiUtils.getClientRect(body)
            },
            _onTitlebarMouseDown: function(evt, el) {
                if (this.draggable) {
                    var rect;
                    var vpRect = uiUtils.getViewportRect();
                    var me = this;
                    uiUtils.startDrag(evt, {
                        ondragstart: function() {
                            rect = uiUtils.getClientRect(me.getDom());
                            me.getDom("contmask").style.visibility = "visible";
                            me.dragMask.show(me.getDom().style.zIndex - 1)
                        },
                        ondragmove: function(x, y) {
                            var left = rect.left + x;
                            var top = rect.top + y;
                            me.safeSetOffset({
                                left: left,
                                top: top
                            })
                        },
                        ondragstop: function() {
                            me.getDom("contmask").style.visibility = "hidden";
                            domUtils.removeClasses(me.getDom(), ["edui-state-centered"]);
                            me.dragMask.hide()
                        }
                    })
                }
            },
            reset: function() {
                this.getDom("content").innerHTML = this.getContentHtml();
                this.fireEvent("dialogafterreset")
            },
            _show: function() {
                if (this._hidden) {
                    this.getDom().style.display = "";
                    this.editor.container.style.zIndex && (this.getDom().style.zIndex = this.editor.container.style.zIndex * 1 + 10);
                    this._hidden = false;
                    this.fireEvent("show");
                    baidu.editor.ui.uiUtils.getFixedLayer().style.zIndex = this.getDom().style.zIndex - 4
                }
            },
            isHidden: function() {
                return this._hidden
            },
            _hide: function() {
                if (!this._hidden) {
                    var wrapNode = this.getDom();
                    wrapNode.style.display = "none";
                    wrapNode.style.zIndex = "";
                    wrapNode.style.width = "";
                    wrapNode.style.height = "";
                    this._hidden = true;
                    this.fireEvent("hide")
                }
            },
            open: function() {
                if (this.autoReset) {
                    try {
                        this.reset()
                    } catch (e) {
                        this.render();
                        this.open()
                    }
                }
                this.showAtCenter();
                if (this.iframeUrl) {
                    try {
                        this.getDom("iframe").focus()
                    } catch (ex) {}
                }
                activeDialog = this
            },
            _onCloseButtonClick: function(evt, el) {
                this.close(false)
            },
            close: function(ok) {
                if (this.fireEvent("close", ok) !== false) {
                    if (this.fullscreen) {
                        document.documentElement.style.overflowX = this._originalContext.html.overflowX;
                        document.documentElement.style.overflowY = this._originalContext.html.overflowY;
                        document.body.style.overflowX = this._originalContext.body.overflowX;
                        document.body.style.overflowY = this._originalContext.body.overflowY;
                        delete this._originalContext
                    }
                    this._hide();
                    var content = this.getDom("content");
                    var iframe = this.getDom("iframe");
                    if (content && iframe) {
                        var doc = iframe.contentDocument || iframe.contentWindow.document;
                        doc && (doc.body.innerHTML = "");
                        domUtils.remove(content)
                    }
                }
            }
        };
        utils.inherits(Dialog, UIBase)
    })();
    (function() {
        var utils = baidu.editor.utils,
            Menu = baidu.editor.ui.Menu,
            SplitButton = baidu.editor.ui.SplitButton,
            MenuButton = baidu.editor.ui.MenuButton = function(options) {
                this.initOptions(options);
                this.initMenuButton()
            };
        MenuButton.prototype = {
            initMenuButton: function() {
                var me = this;
                this.uiName = "menubutton";
                this.popup = new Menu({
                    items: me.items,
                    className: me.className,
                    editor: me.editor
                });
                this.popup.addListener("show", function() {
                    var list = this;
                    for (var i = 0; i < list.items.length; i++) {
                        list.items[i].removeState("checked");
                        if (list.items[i].value == me._value) {
                            list.items[i].addState("checked");
                            this.value = me._value
                        }
                    }
                });
                this.initSplitButton()
            },
            setValue: function(value) {
                this._value = value
            }
        };
        utils.inherits(MenuButton, SplitButton)
    })();
    (function() {
        var utils = baidu.editor.utils,
            Popup = baidu.editor.ui.Popup,
            SplitButton = baidu.editor.ui.SplitButton,
            MultiMenuPop = baidu.editor.ui.MultiMenuPop = function(options) {
                this.initOptions(options);
                this.initMultiMenu()
            };
        MultiMenuPop.prototype = {
            initMultiMenu: function() {
                var me = this;
                this.popup = new Popup({
                    content: "",
                    editor: me.editor,
                    iframe_rendered: false,
                    onshow: function() {
                        if (!this.iframe_rendered) {
                            this.iframe_rendered = true;
                            this.getDom("content").innerHTML = '<iframe id="' + me.id + '_iframe" src="' + me.iframeUrl + '" frameborder="0"></iframe>';
                            me.editor.container.style.zIndex && (this.getDom().style.zIndex = me.editor.container.style.zIndex * 1 + 1)
                        }
                    }
                });
                this.onbuttonclick = function() {
                    this.showPopup()
                };
                this.initSplitButton()
            }
        };
        utils.inherits(MultiMenuPop, SplitButton)
    })();
    (function() {
        var UI = baidu.editor.ui,
            UIBase = UI.UIBase,
            uiUtils = UI.uiUtils,
            utils = baidu.editor.utils,
            domUtils = baidu.editor.dom.domUtils;
        var allMenus = [],
            timeID, isSubMenuShow = false;
        var ShortCutMenu = UI.ShortCutMenu = function(options) {
            this.initOptions(options);
            this.initShortCutMenu()
        };
        ShortCutMenu.postHide = hideAllMenu;
        ShortCutMenu.prototype = {
            isHidden: true,
            SPACE: 5,
            initShortCutMenu: function() {
                this.items = this.items || [];
                this.initUIBase();
                this.initItems();
                this.initEvent();
                allMenus.push(this)
            },
            initEvent: function() {
                var me = this,
                    doc = me.editor.document;
                domUtils.on(doc, "mousemove", function(e) {
                    if (me.isHidden === false) {
                        if (me.getSubMenuMark() || me.eventType == "contextmenu") {
                            return
                        }
                        var flag = true,
                            el = me.getDom(),
                            wt = el.offsetWidth,
                            ht = el.offsetHeight,
                            distanceX = wt / 2 + me.SPACE,
                            distanceY = ht / 2,
                            x = Math.abs(e.screenX - me.left),
                            y = Math.abs(e.screenY - me.top);
                        clearTimeout(timeID);
                        timeID = setTimeout(function() {
                            if (y > 0 && y < distanceY) {
                                me.setOpacity(el, "1")
                            } else {
                                if (y > distanceY && y < distanceY + 70) {
                                    me.setOpacity(el, "0.5");
                                    flag = false
                                } else {
                                    if (y > distanceY + 70 && y < distanceY + 140) {
                                        me.hide()
                                    }
                                }
                            }
                            if (flag && x > 0 && x < distanceX) {
                                me.setOpacity(el, "1")
                            } else {
                                if (x > distanceX && x < distanceX + 70) {
                                    me.setOpacity(el, "0.5")
                                } else {
                                    if (x > distanceX + 70 && x < distanceX + 140) {
                                        me.hide()
                                    }
                                }
                            }
                        })
                    }
                });
                if (browser.chrome) {
                    domUtils.on(doc, "mouseout", function(e) {
                        var relatedTgt = e.relatedTarget || e.toElement;
                        if (relatedTgt == null || relatedTgt.tagName == "HTML") {
                            me.hide()
                        }
                    })
                }
                me.editor.addListener("afterhidepop", function() {
                    if (!me.isHidden) {
                        isSubMenuShow = true
                    }
                })
            },
            initItems: function() {
                if (utils.isArray(this.items)) {
                    for (var i = 0, len = this.items.length; i < len; i++) {
                        var item = this.items[i].toLowerCase();
                        if (UI[item]) {
                            this.items[i] = new UI[item](this.editor);
                            this.items[i].className += " edui-shortcutsubmenu "
                        }
                    }
                }
            },
            setOpacity: function(el, value) {
                if (browser.ie && browser.version < 9) {
                    el.style.filter = "alpha(opacity = " + parseFloat(value) * 100 + ");"
                } else {
                    el.style.opacity = value
                }
            },
            getSubMenuMark: function() {
                isSubMenuShow = false;
                var layerEle = uiUtils.getFixedLayer();
                var list = domUtils.getElementsByTagName(layerEle, "div", function(node) {
                    return domUtils.hasClass(node, "edui-shortcutsubmenu edui-popup")
                });
                for (var i = 0, node; node = list[i++];) {
                    if (node.style.display != "none") {
                        isSubMenuShow = true
                    }
                }
                return isSubMenuShow
            },
            show: function(e, hasContextmenu) {
                var me = this,
                    offset = {},
                    el = this.getDom(),
                    fixedlayer = uiUtils.getFixedLayer();

                function setPos(offset) {
                    if (offset.left < 0) {
                        offset.left = 0
                    }
                    if (offset.top < 0) {
                        offset.top = 0
                    }
                    el.style.cssText = "position:absolute;left:" + offset.left + "px;top:" + offset.top + "px;"
                }
                function setPosByCxtMenu(menu) {
                    if (!menu.tagName) {
                        menu = menu.getDom()
                    }
                    offset.left = parseInt(menu.style.left);
                    offset.top = parseInt(menu.style.top);
                    offset.top -= el.offsetHeight + 15;
                    setPos(offset)
                }
                me.eventType = e.type;
                el.style.cssText = "display:block;left:-9999px";
                if (e.type == "contextmenu" && hasContextmenu) {
                    var menu = domUtils.getElementsByTagName(fixedlayer, "div", "edui-contextmenu")[0];
                    if (menu) {
                        setPosByCxtMenu(menu)
                    } else {
                        me.editor.addListener("aftershowcontextmenu", function(type, menu) {
                            setPosByCxtMenu(menu)
                        })
                    }
                } else {
                    offset = uiUtils.getViewportOffsetByEvent(e);
                    offset.top -= el.offsetHeight + me.SPACE;
                    offset.left += me.SPACE + 20;
                    setPos(offset);
                    me.setOpacity(el, 0.2)
                }
                me.isHidden = false;
                me.left = e.screenX + el.offsetWidth / 2 - me.SPACE;
                me.top = e.screenY - (el.offsetHeight / 2) - me.SPACE;
                if (me.editor) {
                    el.style.zIndex = me.editor.container.style.zIndex * 1 + 10;
                    fixedlayer.style.zIndex = el.style.zIndex - 1
                }
            },
            hide: function() {
                if (this.getDom()) {
                    this.getDom().style.display = "none"
                }
                this.isHidden = true
            },
            postRender: function() {
                if (utils.isArray(this.items)) {
                    for (var i = 0, item; item = this.items[i++];) {
                        item.postRender()
                    }
                }
            },
            getHtmlTpl: function() {
                var buff;
                if (utils.isArray(this.items)) {
                    buff = [];
                    for (var i = 0; i < this.items.length; i++) {
                        buff[i] = this.items[i].renderHtml()
                    }
                    buff = buff.join("")
                } else {
                    buff = this.items
                }
                return '<div id="##" class="%% edui-toolbar" data-src="shortcutmenu" onmousedown="return false;" onselectstart="return false;" >' + buff + "</div>"
            }
        };
        utils.inherits(ShortCutMenu, UIBase);

        function hideAllMenu(e) {
            var tgt = e.target || e.srcElement,
                cur = domUtils.findParent(tgt, function(node) {
                    return domUtils.hasClass(node, "edui-shortcutmenu") || domUtils.hasClass(node, "edui-popup")
                }, true);
            if (!cur) {
                for (var i = 0, menu; menu = allMenus[i++];) {
                    menu.hide()
                }
            }
        }
        domUtils.on(document, "mousedown", function(e) {
            hideAllMenu(e)
        });
        domUtils.on(window, "scroll", function(e) {
            hideAllMenu(e)
        })
    })();
    (function() {
        var utils = baidu.editor.utils,
            UIBase = baidu.editor.ui.UIBase,
            Breakline = baidu.editor.ui.Breakline = function(options) {
                this.initOptions(options);
                this.initSeparator()
            };
        Breakline.prototype = {
            uiName: "Breakline",
            initSeparator: function() {
                this.initUIBase()
            },
            getHtmlTpl: function() {
                return "<br/>"
            }
        };
        utils.inherits(Breakline, UIBase)
    })();
    (function() {
        var utils = baidu.editor.utils,
            domUtils = baidu.editor.dom.domUtils,
            UIBase = baidu.editor.ui.UIBase,
            Message = baidu.editor.ui.Message = function(options) {
                this.initOptions(options);
                this.initMessage()
            };
        Message.prototype = {
            initMessage: function() {
                this.initUIBase()
            },
            getHtmlTpl: function() {
                return '<div id="##" class="edui-message %%">' + ' <div id="##_closer" class="edui-message-closer">×</div>' + ' <div id="##_body" class="edui-message-body edui-message-type-info">' + ' <iframe style="position:absolute;z-index:-1;left:0;top:0;background-color: transparent;" frameborder="0" width="100%" height="100%" src="about:blank"></iframe>' + ' <div class="edui-shadow"></div>' + ' <div id="##_content" class="edui-message-content">' + "  </div>" + " </div>" + "</div>"
            },
            reset: function(opt) {
                var me = this;
                if (!opt.keepshow) {
                    clearTimeout(this.timer);
                    me.timer = setTimeout(function() {
                        me.hide()
                    }, opt.timeout || 4000)
                }
                opt.content !== undefined && me.setContent(opt.content);
                opt.type !== undefined && me.setType(opt.type);
                me.show()
            },
            postRender: function() {
                var me = this,
                    closer = this.getDom("closer");
                closer && domUtils.on(closer, "click", function() {
                    me.hide()
                })
            },
            setContent: function(content) {
                this.getDom("content").innerHTML = content
            },
            setType: function(type) {
                type = type || "info";
                var body = this.getDom("body");
                body.className = body.className.replace(/edui-message-type-[\w-]+/, "edui-message-type-" + type)
            },
            getContent: function() {
                return this.getDom("content").innerHTML
            },
            getType: function() {
                var arr = this.getDom("body").match(/edui-message-type-([\w-]+)/);
                return arr ? arr[1] : ""
            },
            show: function() {
                this.getDom().style.display = "block"
            },
            hide: function() {
                var dom = this.getDom();
                if (dom) {
                    dom.style.display = "none";
                    dom.parentNode && dom.parentNode.removeChild(dom)
                }
            }
        };
        utils.inherits(Message, UIBase)
    })();
    (function() {
        var utils = baidu.editor.utils;
        var editorui = baidu.editor.ui;
        var _Dialog = editorui.Dialog;
        editorui.buttons = {};
        editorui.Dialog = function(options) {
            var dialog = new _Dialog(options);
            dialog.addListener("hide", function() {
                if (dialog.editor) {
                    var editor = dialog.editor;
                    try {
                        if (browser.gecko) {
                            var y = editor.window.scrollY,
                                x = editor.window.scrollX;
                            editor.body.focus();
                            editor.window.scrollTo(x, y)
                        } else {
                            editor.focus()
                        }
                    } catch (ex) {}
                }
            });
            return dialog
        };
        var iframeUrlMap = {
            "anchor": "~/dialogs/anchor/anchor.html",
            "insertimage": "~/dialogs/image/image.html",
            "link": "~/dialogs/link/link.html",
            "spechars": "~/dialogs/spechars/spechars.html",
            "searchreplace": "~/dialogs/searchreplace/searchreplace.html",
            "map": "~/dialogs/map/map.html",
            "gmap": "~/dialogs/gmap/gmap.html",
            "insertvideo": "~/dialogs/video/video.html",
            "help": "~/dialogs/help/help.html",
            "preview": "~/dialogs/preview/preview.html",
            "emotion": "~/dialogs/emotion/emotion.html",
            "wordimage": "~/dialogs/wordimage/wordimage.html",
            "attachment": "~/dialogs/attachment/attachment.html",
            "insertframe": "~/dialogs/insertframe/insertframe.html",
            "edittip": "~/dialogs/table/edittip.html",
            "edittable": "~/dialogs/table/edittable.html",
            "edittd": "~/dialogs/table/edittd.html",
            "webapp": "~/dialogs/webapp/webapp.html",
            "snapscreen": "~/dialogs/snapscreen/snapscreen.html",
            "scrawl": "~/dialogs/scrawl/scrawl.html",
            "music": "~/dialogs/music/music.html",
            "template": "~/dialogs/template/template.html",
            "background": "~/dialogs/background/background.html",
            "charts": "~/dialogs/charts/charts.html"
        };
        var btnCmds = ["undo", "redo", "formatmatch", "bold", "italic", "underline", "fontborder", "touppercase", "tolowercase", "strikethrough", "subscript", "superscript", "source", "indent", "outdent", "blockquote", "pasteplain", "pagebreak", "selectall", "print", "horizontal", "removeformat", "time", "date", "unlink", "insertparagraphbeforetable", "insertrow", "insertcol", "mergeright", "mergedown", "deleterow", "deletecol", "splittorows", "splittocols", "splittocells", "mergecells", "deletetable", "drafts"];
        for (var i = 0, ci; ci = btnCmds[i++];) {
            ci = ci.toLowerCase();
            editorui[ci] = function(cmd) {
                return function(editor) {
                    var ui = new editorui.Button({
                        className: "edui-for-" + cmd,
                        title: editor.options.labelMap[cmd] || editor.getLang("labelMap." + cmd) || "",
                        onclick: function() {
                            editor.execCommand(cmd)
                        },
                        theme: editor.options.theme,
                        showText: false
                    });
                    editorui.buttons[cmd] = ui;
                    editor.addListener("selectionchange", function(type, causeByUi, uiReady) {
                        var state = editor.queryCommandState(cmd);
                        if (state == -1) {
                            ui.setDisabled(true);
                            ui.setChecked(false)
                        } else {
                            if (!uiReady) {
                                ui.setDisabled(false);
                                ui.setChecked(state)
                            }
                        }
                    });
                    return ui
                }
            }(ci)
        }
        editorui.cleardoc = function(editor) {
            var ui = new editorui.Button({
                className: "edui-for-cleardoc",
                title: editor.options.labelMap.cleardoc || editor.getLang("labelMap.cleardoc") || "",
                theme: editor.options.theme,
                onclick: function() {
                    if (confirm(editor.getLang("confirmClear"))) {
                        editor.execCommand("cleardoc")
                    }
                }
            });
            editorui.buttons["cleardoc"] = ui;
            editor.addListener("selectionchange", function() {
                ui.setDisabled(editor.queryCommandState("cleardoc") == -1)
            });
            return ui
        };
        var typeset = {
            "justify": ["left", "right", "center", "justify"],
            "imagefloat": ["none", "left", "center", "right"],
            "directionality": ["ltr", "rtl"]
        };
        for (var p in typeset) {
            (function(cmd, val) {
                for (var i = 0, ci; ci = val[i++];) {
                    (function(cmd2) {
                        editorui[cmd.replace("float", "") + cmd2] = function(editor) {
                            var ui = new editorui.Button({
                                className: "edui-for-" + cmd.replace("float", "") + cmd2,
                                title: editor.options.labelMap[cmd.replace("float", "") + cmd2] || editor.getLang("labelMap." + cmd.replace("float", "") + cmd2) || "",
                                theme: editor.options.theme,
                                onclick: function() {
                                    editor.execCommand(cmd, cmd2)
                                }
                            });
                            editorui.buttons[cmd] = ui;
                            editor.addListener("selectionchange", function(type, causeByUi, uiReady) {
                                ui.setDisabled(editor.queryCommandState(cmd) == -1);
                                ui.setChecked(editor.queryCommandValue(cmd) == cmd2 && !uiReady)
                            });
                            return ui
                        }
                    })(ci)
                }
            })(p, typeset[p])
        }
        for (var i = 0, ci; ci = ["backcolor", "forecolor"][i++];) {
            editorui[ci] = function(cmd) {
                return function(editor) {
                    var ui = new editorui.ColorButton({
                        className: "edui-for-" + cmd,
                        color: "default",
                        title: editor.options.labelMap[cmd] || editor.getLang("labelMap." + cmd) || "",
                        editor: editor,
                        onpickcolor: function(t, color) {
                            editor.execCommand(cmd, color)
                        },
                        onpicknocolor: function() {
                            editor.execCommand(cmd, "default");
                            this.setColor("transparent");
                            this.color = "default"
                        },
                        onbuttonclick: function() {
                            editor.execCommand(cmd, this.color)
                        }
                    });
                    editorui.buttons[cmd] = ui;
                    editor.addListener("selectionchange", function() {
                        ui.setDisabled(editor.queryCommandState(cmd) == -1)
                    });
                    return ui
                }
            }(ci)
        }
        var dialogBtns = {
            noOk: ["searchreplace", "help", "spechars", "webapp", "preview"],
            ok: ["attachment", "anchor", "link", "insertimage", "map", "gmap", "insertframe", "wordimage", "insertvideo", "insertframe", "edittip", "edittable", "edittd", "scrawl", "template", "music", "background", "charts"]
        };
        for (var p in dialogBtns) {
            (function(type, vals) {
                for (var i = 0, ci; ci = vals[i++];) {
                    if (browser.opera && ci === "searchreplace") {
                        continue
                    }(function(cmd) {
                        editorui[cmd] = function(editor, iframeUrl, title) {
                            iframeUrl = iframeUrl || (editor.options.iframeUrlMap || {})[cmd] || iframeUrlMap[cmd];
                            title = editor.options.labelMap[cmd] || editor.getLang("labelMap." + cmd) || "";
                            var dialog;
                            if (iframeUrl) {
                                dialog = new editorui.Dialog(utils.extend({
                                    iframeUrl: editor.ui.mapUrl(iframeUrl),
                                    editor: editor,
                                    className: "edui-for-" + cmd,
                                    title: title,
                                    holdScroll: cmd === "insertimage",
                                    fullscreen: /charts|preview/.test(cmd),
                                    closeDialog: editor.getLang("closeDialog")
                                }, type == "ok" ? {
                                    buttons: [{
                                        className: "edui-okbutton",
                                        label: editor.getLang("ok"),
                                        editor: editor,
                                        onclick: function() {
                                            dialog.close(true)
                                        }
                                    }, {
                                        className: "edui-cancelbutton",
                                        label: editor.getLang("cancel"),
                                        editor: editor,
                                        onclick: function() {
                                            dialog.close(false)
                                        }
                                    }]
                                } : {}));
                                editor.ui._dialogs[cmd + "Dialog"] = dialog
                            }
                            var ui = new editorui.Button({
                                className: "edui-for-" + cmd,
                                title: title,
                                onclick: function() {
                                    if (dialog) {
                                        switch (cmd) {
                                            case "wordimage":
                                                var images = editor.execCommand("wordimage");
                                                if (images && images.length) {
                                                    dialog.render();
                                                    dialog.open()
                                                }
                                                break;
                                            case "scrawl":
                                                if (editor.queryCommandState("scrawl") != -1) {
                                                    dialog.render();
                                                    dialog.open()
                                                }
                                                break;
                                            default:
                                                dialog.render();
                                                dialog.open()
                                        }
                                    }
                                },
                                theme: editor.options.theme,
                                disabled: (cmd == "scrawl" && editor.queryCommandState("scrawl") == -1) || (cmd == "charts")
                            });
                            editorui.buttons[cmd] = ui;
                            editor.addListener("selectionchange", function() {
                                var unNeedCheckState = {
                                    "edittable": 1
                                };
                                if (cmd in unNeedCheckState) {
                                    return
                                }
                                var state = editor.queryCommandState(cmd);
                                if (ui.getDom()) {
                                    ui.setDisabled(state == -1);
                                    ui.setChecked(state)
                                }
                            });
                            return ui
                        }
                    })(ci.toLowerCase())
                }
            })(p, dialogBtns[p])
        }
        editorui.snapscreen = function(editor, iframeUrl, title) {
            title = editor.options.labelMap["snapscreen"] || editor.getLang("labelMap.snapscreen") || "";
            var ui = new editorui.Button({
                className: "edui-for-snapscreen",
                title: title,
                onclick: function() {
                    editor.execCommand("snapscreen")
                },
                theme: editor.options.theme
            });
            editorui.buttons["snapscreen"] = ui;
            iframeUrl = iframeUrl || (editor.options.iframeUrlMap || {})["snapscreen"] || iframeUrlMap["snapscreen"];
            if (iframeUrl) {
                var dialog = new editorui.Dialog({
                    iframeUrl: editor.ui.mapUrl(iframeUrl),
                    editor: editor,
                    className: "edui-for-snapscreen",
                    title: title,
                    buttons: [{
                        className: "edui-okbutton",
                        label: editor.getLang("ok"),
                        editor: editor,
                        onclick: function() {
                            dialog.close(true)
                        }
                    }, {
                        className: "edui-cancelbutton",
                        label: editor.getLang("cancel"),
                        editor: editor,
                        onclick: function() {
                            dialog.close(false)
                        }
                    }]
                });
                dialog.render();
                editor.ui._dialogs["snapscreenDialog"] = dialog
            }
            editor.addListener("selectionchange", function() {
                ui.setDisabled(editor.queryCommandState("snapscreen") == -1)
            });
            return ui
        };
        editorui.insertcode = function(editor, list, title) {
            list = editor.options["insertcode"] || [];
            title = editor.options.labelMap["insertcode"] || editor.getLang("labelMap.insertcode") || "";
            var items = [];
            utils.each(list, function(key, val) {
                items.push({
                    label: key,
                    value: val,
                    theme: editor.options.theme,
                    renderLabelHtml: function() {
                        return '<div class="edui-label %%-label" >' + (this.label || "") + "</div>"
                    }
                })
            });
            var ui = new editorui.Combox({
                editor: editor,
                items: items,
                onselect: function(t, index) {
                    editor.execCommand("insertcode", this.items[index].value)
                },
                onbuttonclick: function() {
                    this.showPopup()
                },
                title: title,
                initValue: title,
                className: "edui-for-insertcode",
                indexByValue: function(value) {
                    if (value) {
                        for (var i = 0, ci; ci = this.items[i]; i++) {
                            if (ci.value.indexOf(value) != -1) {
                                return i
                            }
                        }
                    }
                    return -1
                }
            });
            editorui.buttons["insertcode"] = ui;
            editor.addListener("selectionchange", function(type, causeByUi, uiReady) {
                if (!uiReady) {
                    var state = editor.queryCommandState("insertcode");
                    if (state == -1) {
                        ui.setDisabled(true)
                    } else {
                        ui.setDisabled(false);
                        var value = editor.queryCommandValue("insertcode");
                        if (!value) {
                            ui.setValue(title);
                            return
                        }
                        value && (value = value.replace(/['"]/g, "").split(",")[0]);
                        ui.setValue(value)
                    }
                }
            });
            return ui
        };
        editorui.fontfamily = function(editor, list, title) {
            list = editor.options["fontfamily"] || [];
            title = editor.options.labelMap["fontfamily"] || editor.getLang("labelMap.fontfamily") || "";
            if (!list.length) {
                return
            }
            for (var i = 0, ci, items = []; ci = list[i]; i++) {
                var langLabel = editor.getLang("fontfamily")[ci.name] || "";
                (function(key, val) {
                    items.push({
                        label: key,
                        value: val,
                        theme: editor.options.theme,
                        renderLabelHtml: function() {
                            return '<div class="edui-label %%-label" style="font-family:' + utils.unhtml(this.value) + '">' + (this.label || "") + "</div>"
                        }
                    })
                })(ci.label || langLabel, ci.val)
            }
            var ui = new editorui.Combox({
                editor: editor,
                items: items,
                onselect: function(t, index) {
                    editor.execCommand("FontFamily", this.items[index].value)
                },
                onbuttonclick: function() {
                    this.showPopup()
                },
                title: title,
                initValue: title,
                className: "edui-for-fontfamily",
                indexByValue: function(value) {
                    if (value) {
                        for (var i = 0, ci; ci = this.items[i]; i++) {
                            if (ci.value.indexOf(value) != -1) {
                                return i
                            }
                        }
                    }
                    return -1
                }
            });
            editorui.buttons["fontfamily"] = ui;
            editor.addListener("selectionchange", function(type, causeByUi, uiReady) {
                if (!uiReady) {
                    var state = editor.queryCommandState("FontFamily");
                    if (state == -1) {
                        ui.setDisabled(true)
                    } else {
                        ui.setDisabled(false);
                        var value = editor.queryCommandValue("FontFamily");
                        value && (value = value.replace(/['"]/g, "").split(",")[0]);
                        ui.setValue(value)
                    }
                }
            });
            return ui
        };
        editorui.fontsize = function(editor, list, title) {
            title = editor.options.labelMap["fontsize"] || editor.getLang("labelMap.fontsize") || "";
            list = list || editor.options["fontsize"] || [];
            if (!list.length) {
                return
            }
            var items = [];
            for (var i = 0; i < list.length; i++) {
                var size = list[i] + "px";
                items.push({
                    label: size,
                    value: size,
                    theme: editor.options.theme,
                    renderLabelHtml: function() {
                        return '<div class="edui-label %%-label" style="line-height:1;font-size:' + this.value + '">' + (this.label || "") + "</div>"
                    }
                })
            }
            var ui = new editorui.Combox({
                editor: editor,
                items: items,
                title: title,
                initValue: title,
                onselect: function(t, index) {
                    editor.execCommand("FontSize", this.items[index].value)
                },
                onbuttonclick: function() {
                    this.showPopup()
                },
                className: "edui-for-fontsize"
            });
            editorui.buttons["fontsize"] = ui;
            editor.addListener("selectionchange", function(type, causeByUi, uiReady) {
                if (!uiReady) {
                    var state = editor.queryCommandState("FontSize");
                    if (state == -1) {
                        ui.setDisabled(true)
                    } else {
                        ui.setDisabled(false);
                        ui.setValue(editor.queryCommandValue("FontSize"))
                    }
                }
            });
            return ui
        };
        editorui.paragraph = function(editor, list, title) {
            title = editor.options.labelMap["paragraph"] || editor.getLang("labelMap.paragraph") || "";
            list = editor.options["paragraph"] || [];
            if (utils.isEmptyObject(list)) {
                return
            }
            var items = [];
            for (var i in list) {
                items.push({
                    value: i,
                    label: list[i] || editor.getLang("paragraph")[i],
                    theme: editor.options.theme,
                    renderLabelHtml: function() {
                        return '<div class="edui-label %%-label"><span class="edui-for-' + this.value + '">' + (this.label || "") + "</span></div>"
                    }
                })
            }
            var ui = new editorui.Combox({
                editor: editor,
                items: items,
                title: title,
                initValue: title,
                className: "edui-for-paragraph",
                onselect: function(t, index) {
                    editor.execCommand("Paragraph", this.items[index].value)
                },
                onbuttonclick: function() {
                    this.showPopup()
                }
            });
            editorui.buttons["paragraph"] = ui;
            editor.addListener("selectionchange", function(type, causeByUi, uiReady) {
                if (!uiReady) {
                    var state = editor.queryCommandState("Paragraph");
                    if (state == -1) {
                        ui.setDisabled(true)
                    } else {
                        ui.setDisabled(false);
                        var value = editor.queryCommandValue("Paragraph");
                        var index = ui.indexByValue(value);
                        if (index != -1) {
                            ui.setValue(value)
                        } else {
                            ui.setValue(ui.initValue)
                        }
                    }
                }
            });
            return ui
        };
        editorui.customstyle = function(editor) {
            var list = editor.options["customstyle"] || [],
                title = editor.options.labelMap["customstyle"] || editor.getLang("labelMap.customstyle") || "";
            if (!list.length) {
                return
            }
            var langCs = editor.getLang("customstyle");
            for (var i = 0, items = [], t; t = list[i++];) {
                (function(t) {
                    var ck = {};
                    ck.label = t.label ? t.label : langCs[t.name];
                    ck.style = t.style;
                    ck.className = t.className;
                    ck.tag = t.tag;
                    items.push({
                        label: ck.label,
                        value: ck,
                        theme: editor.options.theme,
                        renderLabelHtml: function() {
                            return '<div class="edui-label %%-label">' + "<" + ck.tag + " " + (ck.className ? ' class="' + ck.className + '"' : "") + (ck.style ? ' style="' + ck.style + '"' : "") + ">" + ck.label + "</" + ck.tag + ">" + "</div>"
                        }
                    })
                })(t)
            }
            var ui = new editorui.Combox({
                editor: editor,
                items: items,
                title: title,
                initValue: title,
                className: "edui-for-customstyle",
                onselect: function(t, index) {
                    editor.execCommand("customstyle", this.items[index].value)
                },
                onbuttonclick: function() {
                    this.showPopup()
                },
                indexByValue: function(value) {
                    for (var i = 0, ti; ti = this.items[i++];) {
                        if (ti.label == value) {
                            return i - 1
                        }
                    }
                    return -1
                }
            });
            editorui.buttons["customstyle"] = ui;
            editor.addListener("selectionchange", function(type, causeByUi, uiReady) {
                if (!uiReady) {
                    var state = editor.queryCommandState("customstyle");
                    if (state == -1) {
                        ui.setDisabled(true)
                    } else {
                        ui.setDisabled(false);
                        var value = editor.queryCommandValue("customstyle");
                        var index = ui.indexByValue(value);
                        if (index != -1) {
                            ui.setValue(value)
                        } else {
                            ui.setValue(ui.initValue)
                        }
                    }
                }
            });
            return ui
        };
        editorui.inserttable = function(editor, iframeUrl, title) {
            title = editor.options.labelMap["inserttable"] || editor.getLang("labelMap.inserttable") || "";
            var ui = new editorui.TableButton({
                editor: editor,
                title: title,
                className: "edui-for-inserttable",
                onpicktable: function(t, numCols, numRows) {
                    editor.execCommand("InsertTable", {
                        numRows: numRows,
                        numCols: numCols,
                        border: 1
                    })
                },
                onbuttonclick: function() {
                    this.showPopup()
                }
            });
            editorui.buttons["inserttable"] = ui;
            editor.addListener("selectionchange", function() {
                ui.setDisabled(editor.queryCommandState("inserttable") == -1)
            });
            return ui
        };
        editorui.lineheight = function(editor) {
            var val = editor.options.lineheight || [];
            if (!val.length) {
                return
            }
            for (var i = 0, ci, items = []; ci = val[i++];) {
                items.push({
                    label: ci,
                    value: ci,
                    theme: editor.options.theme,
                    onclick: function() {
                        editor.execCommand("lineheight", this.value)
                    }
                })
            }
            var ui = new editorui.MenuButton({
                editor: editor,
                className: "edui-for-lineheight",
                title: editor.options.labelMap["lineheight"] || editor.getLang("labelMap.lineheight") || "",
                items: items,
                onbuttonclick: function() {
                    var value = editor.queryCommandValue("LineHeight") || this.value;
                    editor.execCommand("LineHeight", value)
                }
            });
            editorui.buttons["lineheight"] = ui;
            editor.addListener("selectionchange", function() {
                var state = editor.queryCommandState("LineHeight");
                if (state == -1) {
                    ui.setDisabled(true)
                } else {
                    ui.setDisabled(false);
                    var value = editor.queryCommandValue("LineHeight");
                    value && ui.setValue((value + "").replace(/cm/, ""));
                    ui.setChecked(state)
                }
            });
            return ui
        };
        var rowspacings = ["top", "bottom"];
        for (var r = 0, ri; ri = rowspacings[r++];) {
            (function(cmd) {
                editorui["rowspacing" + cmd] = function(editor) {
                    var val = editor.options["rowspacing" + cmd] || [];
                    if (!val.length) {
                        return null
                    }
                    for (var i = 0, ci, items = []; ci = val[i++];) {
                        items.push({
                            label: ci,
                            value: ci,
                            theme: editor.options.theme,
                            onclick: function() {
                                editor.execCommand("rowspacing", this.value, cmd)
                            }
                        })
                    }
                    var ui = new editorui.MenuButton({
                        editor: editor,
                        className: "edui-for-rowspacing" + cmd,
                        title: editor.options.labelMap["rowspacing" + cmd] || editor.getLang("labelMap.rowspacing" + cmd) || "",
                        items: items,
                        onbuttonclick: function() {
                            var value = editor.queryCommandValue("rowspacing", cmd) || this.value;
                            editor.execCommand("rowspacing", value, cmd)
                        }
                    });
                    editorui.buttons[cmd] = ui;
                    editor.addListener("selectionchange", function() {
                        var state = editor.queryCommandState("rowspacing", cmd);
                        if (state == -1) {
                            ui.setDisabled(true)
                        } else {
                            ui.setDisabled(false);
                            var value = editor.queryCommandValue("rowspacing", cmd);
                            value && ui.setValue((value + "").replace(/%/, ""));
                            ui.setChecked(state)
                        }
                    });
                    return ui
                }
            })(ri)
        }
        var lists = ["insertorderedlist", "insertunorderedlist"];
        for (var l = 0, cl; cl = lists[l++];) {
            (function(cmd) {
                editorui[cmd] = function(editor) {
                    var vals = editor.options[cmd],
                        _onMenuClick = function() {
                            editor.execCommand(cmd, this.value)
                        },
                        items = [];
                    for (var i in vals) {
                        items.push({
                            label: vals[i] || editor.getLang()[cmd][i] || "",
                            value: i,
                            theme: editor.options.theme,
                            onclick: _onMenuClick
                        })
                    }
                    var ui = new editorui.MenuButton({
                        editor: editor,
                        className: "edui-for-" + cmd,
                        title: editor.getLang("labelMap." + cmd) || "",
                        "items": items,
                        onbuttonclick: function() {
                            var value = editor.queryCommandValue(cmd) || this.value;
                            editor.execCommand(cmd, value)
                        }
                    });
                    editorui.buttons[cmd] = ui;
                    editor.addListener("selectionchange", function() {
                        var state = editor.queryCommandState(cmd);
                        if (state == -1) {
                            ui.setDisabled(true)
                        } else {
                            ui.setDisabled(false);
                            var value = editor.queryCommandValue(cmd);
                            ui.setValue(value);
                            ui.setChecked(state)
                        }
                    });
                    return ui
                }
            })(cl)
        }
        editorui.fullscreen = function(editor, title) {
            title = editor.options.labelMap["fullscreen"] || editor.getLang("labelMap.fullscreen") || "";
            var ui = new editorui.Button({
                className: "edui-for-fullscreen",
                title: title,
                theme: editor.options.theme,
                onclick: function() {
                    if (editor.ui) {
                        editor.ui.setFullScreen(!editor.ui.isFullScreen())
                    }
                    this.setChecked(editor.ui.isFullScreen())
                }
            });
            editorui.buttons["fullscreen"] = ui;
            editor.addListener("selectionchange", function() {
                var state = editor.queryCommandState("fullscreen");
                ui.setDisabled(state == -1);
                ui.setChecked(editor.ui.isFullScreen())
            });
            return ui
        };
        editorui["emotion"] = function(editor, iframeUrl) {
            var cmd = "emotion";
            var ui = new editorui.MultiMenuPop({
                title: editor.options.labelMap[cmd] || editor.getLang("labelMap." + cmd + "") || "",
                editor: editor,
                className: "edui-for-" + cmd,
                iframeUrl: editor.ui.mapUrl(iframeUrl || (editor.options.iframeUrlMap || {})[cmd] || iframeUrlMap[cmd])
            });
            editorui.buttons[cmd] = ui;
            editor.addListener("selectionchange", function() {
                ui.setDisabled(editor.queryCommandState(cmd) == -1)
            });
            return ui
        };
        editorui.autotypeset = function(editor) {
            var ui = new editorui.AutoTypeSetButton({
                editor: editor,
                title: editor.options.labelMap["autotypeset"] || editor.getLang("labelMap.autotypeset") || "",
                className: "edui-for-autotypeset",
                onbuttonclick: function() {
                    editor.execCommand("autotypeset")
                }
            });
            editorui.buttons["autotypeset"] = ui;
            editor.addListener("selectionchange", function() {
                ui.setDisabled(editor.queryCommandState("autotypeset") == -1)
            });
            return ui
        };
        editorui["simpleupload"] = function(editor) {
            var name = "simpleupload",
                ui = new editorui.Button({
                    className: "edui-for-" + name,
                    title: editor.options.labelMap[name] || editor.getLang("labelMap." + name) || "",
                    onclick: function() {},
                    theme: editor.options.theme,
                    showText: false
                });
            editorui.buttons[name] = ui;
            editor.addListener("ready", function() {
                var b = ui.getDom("body"),
                    iconSpan = b.children[0];
                editor.fireEvent("simpleuploadbtnready", iconSpan)
            });
            editor.addListener("selectionchange", function(type, causeByUi, uiReady) {
                var state = editor.queryCommandState(name);
                if (state == -1) {
                    ui.setDisabled(true);
                    ui.setChecked(false)
                } else {
                    if (!uiReady) {
                        ui.setDisabled(false);
                        ui.setChecked(state)
                    }
                }
            });
            return ui
        }
    })();
    (function() {
        var utils = baidu.editor.utils,
            uiUtils = baidu.editor.ui.uiUtils,
            UIBase = baidu.editor.ui.UIBase,
            domUtils = baidu.editor.dom.domUtils;
        var nodeStack = [];

        function EditorUI(options) {
            this.initOptions(options);
            this.initEditorUI()
        }
        EditorUI.prototype = {
            uiName: "editor",
            initEditorUI: function() {
                this.editor.ui = this;
                this._dialogs = {};
                this.initUIBase();
                this._initToolbars();
                var editor = this.editor,
                    me = this;
                editor.addListener("ready", function() {
                    editor.getDialog = function(name) {
                        return editor.ui._dialogs[name + "Dialog"]
                    };
                    domUtils.on(editor.window, "scroll", function(evt) {
                        baidu.editor.ui.Popup.postHide(evt)
                    });
                    editor.ui._actualFrameWidth = editor.options.initialFrameWidth;
                    UE.browser.ie && UE.browser.version === 6 && editor.container.ownerDocument.execCommand("BackgroundImageCache", false, true);
                    if (editor.options.elementPathEnabled) {
                        editor.ui.getDom("elementpath").innerHTML = '<div class="edui-editor-breadcrumb">' + editor.getLang("elementPathTip") + ":</div>"
                    }
                    if (editor.options.wordCount) {
                        function countFn() {
                            setCount(editor, me);
                            domUtils.un(editor.document, "click", arguments.callee)
                        }
                        domUtils.on(editor.document, "click", countFn);
                        editor.ui.getDom("wordcount").innerHTML = editor.getLang("wordCountTip")
                    }
                    editor.ui._scale();
                    if (editor.options.scaleEnabled) {
                        if (editor.autoHeightEnabled) {
                            editor.disableAutoHeight()
                        }
                        me.enableScale()
                    } else {
                        me.disableScale()
                    }
                    if (!editor.options.elementPathEnabled && !editor.options.wordCount && !editor.options.scaleEnabled) {
                        editor.ui.getDom("elementpath").style.display = "none";
                        editor.ui.getDom("wordcount").style.display = "none";
                        editor.ui.getDom("scale").style.display = "none"
                    }
                    if (!editor.selection.isFocus()) {
                        return
                    }
                    editor.fireEvent("selectionchange", false, true)
                });
                editor.addListener("mousedown", function(t, evt) {
                    var el = evt.target || evt.srcElement;
                    baidu.editor.ui.Popup.postHide(evt, el);
                    baidu.editor.ui.ShortCutMenu.postHide(evt)
                });
                editor.addListener("delcells", function() {
                    if (UE.ui["edittip"]) {
                        new UE.ui["edittip"](editor)
                    }
                    editor.getDialog("edittip").open()
                });
                var pastePop, isPaste = false,
                    timer;
                editor.addListener("afterpaste", function() {
                    if (editor.queryCommandState("pasteplain")) {
                        return
                    }
                    if (baidu.editor.ui.PastePicker) {
                        pastePop = new baidu.editor.ui.Popup({
                            content: new baidu.editor.ui.PastePicker({
                                editor: editor
                            }),
                            editor: editor,
                            className: "edui-wordpastepop"
                        });
                        pastePop.render()
                    }
                    isPaste = true
                });
                editor.addListener("afterinserthtml", function() {
                    clearTimeout(timer);
                    timer = setTimeout(function() {
                        if (pastePop && (isPaste || editor.ui._isTransfer)) {
                            if (pastePop.isHidden()) {
                                var span = domUtils.createElement(editor.document, "span", {
                                        "style": "line-height:0px;",
                                        "innerHTML": "﻿"
                                    }),
                                    range = editor.selection.getRange();
                                range.insertNode(span);
                                var tmp = getDomNode(span, "firstChild", "previousSibling");
                                tmp && pastePop.showAnchor(tmp.nodeType == 3 ? tmp.parentNode : tmp);
                                domUtils.remove(span)
                            } else {
                                pastePop.show()
                            }
                            delete editor.ui._isTransfer;
                            isPaste = false
                        }
                    }, 200)
                });
                editor.addListener("contextmenu", function(t, evt) {
                    baidu.editor.ui.Popup.postHide(evt)
                });
                editor.addListener("keydown", function(t, evt) {
                    if (pastePop) {
                        pastePop.dispose(evt)
                    }
                    var keyCode = evt.keyCode || evt.which;
                    if (evt.altKey && keyCode == 90) {
                        UE.ui.buttons["fullscreen"].onclick()
                    }
                });
                editor.addListener("wordcount", function(type) {
                    setCount(this, me)
                });

                function setCount(editor, ui) {
                    editor.setOpt({
                        wordCount: true,
                        maximumWords: 10000,
                        wordCountMsg: editor.options.wordCountMsg || editor.getLang("wordCountMsg"),
                        wordOverFlowMsg: editor.options.wordOverFlowMsg || editor.getLang("wordOverFlowMsg")
                    });
                    var opt = editor.options,
                        max = opt.maximumWords,
                        msg = opt.wordCountMsg,
                        errMsg = opt.wordOverFlowMsg,
                        countDom = ui.getDom("wordcount");
                    if (!opt.wordCount) {
                        return
                    }
                    var count = editor.getContentLength(true);
                    if (count > max) {
                        countDom.innerHTML = errMsg;
                        editor.fireEvent("wordcountoverflow")
                    } else {
                        countDom.innerHTML = msg.replace("{#leave}", max - count).replace("{#count}", count)
                    }
                }
                editor.addListener("selectionchange", function() {
                    if (editor.options.elementPathEnabled) {
                        me[(editor.queryCommandState("elementpath") == -1 ? "dis" : "en") + "ableElementPath"]()
                    }
                    if (editor.options.scaleEnabled) {
                        me[(editor.queryCommandState("scale") == -1 ? "dis" : "en") + "ableScale"]()
                    }
                });
                var popup = new baidu.editor.ui.Popup({
                    editor: editor,
                    content: "",
                    className: "edui-bubble",
                    _onEditButtonClick: function() {
                        this.hide();
                        editor.ui._dialogs.linkDialog.open()
                    },
                    _onImgEditButtonClick: function(name) {
                        this.hide();
                        editor.ui._dialogs[name] && editor.ui._dialogs[name].open()
                    },
                    _onImgSetFloat: function(value) {
                        this.hide();
                        editor.execCommand("imagefloat", value)
                    },
                    _setIframeAlign: function(value) {
                        var frame = popup.anchorEl;
                        var newFrame = frame.cloneNode(true);
                        switch (value) {
                            case -2:
                                newFrame.setAttribute("align", "");
                                break;
                            case -1:
                                newFrame.setAttribute("align", "left");
                                break;
                            case 1:
                                newFrame.setAttribute("align", "right");
                                break
                        }
                        frame.parentNode.insertBefore(newFrame, frame);
                        domUtils.remove(frame);
                        popup.anchorEl = newFrame;
                        popup.showAnchor(popup.anchorEl)
                    },
                    _updateIframe: function() {
                        var frame = editor._iframe = popup.anchorEl;
                        if (domUtils.hasClass(frame, "ueditor_baidumap")) {
                            editor.selection.getRange().selectNode(frame).select();
                            editor.ui._dialogs.mapDialog.open();
                            popup.hide()
                        } else {
                            editor.ui._dialogs.insertframeDialog.open();
                            popup.hide()
                        }
                    },
                    _onRemoveButtonClick: function(cmdName) {
                        editor.execCommand(cmdName);
                        this.hide()
                    },
                    queryAutoHide: function(el) {
                        if (el && el.ownerDocument == editor.document) {
                            if (el.tagName.toLowerCase() == "img" || domUtils.findParentByTagName(el, "a", true)) {
                                return el !== popup.anchorEl
                            }
                        }
                        return baidu.editor.ui.Popup.prototype.queryAutoHide.call(this, el)
                    }
                });
                popup.render();
                if (editor.options.imagePopup) {
                    editor.addListener("mouseover", function(t, evt) {
                        evt = evt || window.event;
                        var el = evt.target || evt.srcElement;
                        if (editor.ui._dialogs.insertframeDialog && /iframe/ig.test(el.tagName)) {
                            var html = popup.formatHtml("<nobr>" + editor.getLang("property") + ': <span onclick=$$._setIframeAlign(-2) class="edui-clickable">' + editor.getLang("default") + '</span>&nbsp;&nbsp;<span onclick=$$._setIframeAlign(-1) class="edui-clickable">' + editor.getLang("justifyleft") + '</span>&nbsp;&nbsp;<span onclick=$$._setIframeAlign(1) class="edui-clickable">' + editor.getLang("justifyright") + "</span>&nbsp;&nbsp;" + ' <span onclick="$$._updateIframe( this);" class="edui-clickable">' + editor.getLang("modify") + "</span></nobr>");
                            if (html) {
                                popup.getDom("content").innerHTML = html;
                                popup.anchorEl = el;
                                popup.showAnchor(popup.anchorEl)
                            } else {
                                popup.hide()
                            }
                        }
                    });
                    editor.addListener("selectionchange", function(t, causeByUi) {
                        if (!causeByUi) {
                            return
                        }
                        var html = "",
                            str = "",
                            img = editor.selection.getRange().getClosedNode(),
                            dialogs = editor.ui._dialogs;
                        if (img && img.tagName == "IMG") {
                            var dialogName = "insertimageDialog";
                            if (img.className.indexOf("edui-faked-video") != -1 || img.className.indexOf("edui-upload-video") != -1) {
                                dialogName = "insertvideoDialog"
                            }
                            if (img.className.indexOf("edui-faked-webapp") != -1) {
                                dialogName = "webappDialog"
                            }
                            if (img.src.indexOf("http://api.map.baidu.com") != -1) {
                                dialogName = "mapDialog"
                            }
                            if (img.className.indexOf("edui-faked-music") != -1) {
                                dialogName = "musicDialog"
                            }
                            if (img.src.indexOf("http://maps.google.com/maps/api/staticmap") != -1) {
                                dialogName = "gmapDialog"
                            }
                            if (img.getAttribute("anchorname")) {
                                dialogName = "anchorDialog";
                                html = popup.formatHtml("<nobr>" + editor.getLang("property") + ': <span onclick=$$._onImgEditButtonClick("anchorDialog") class="edui-clickable">' + editor.getLang("modify") + "</span>&nbsp;&nbsp;" + "<span onclick=$$._onRemoveButtonClick('anchor') class=\"edui-clickable\">" + editor.getLang("delete") + "</span></nobr>")
                            }
                            if (img.getAttribute("word_img")) {
                                editor.word_img = [img.getAttribute("word_img")];
                                dialogName = "wordimageDialog"
                            }
                            if (domUtils.hasClass(img, "loadingclass") || domUtils.hasClass(img, "loaderrorclass")) {
                                dialogName = ""
                            }
                            if (!dialogs[dialogName]) {
                                return
                            }
                            str = "<nobr>" + editor.getLang("property") + ": " + '<span onclick=$$._onImgSetFloat("none") class="edui-clickable">' + editor.getLang("default") + "</span>&nbsp;&nbsp;" + '<span onclick=$$._onImgSetFloat("left") class="edui-clickable">' + editor.getLang("justifyleft") + "</span>&nbsp;&nbsp;" + '<span onclick=$$._onImgSetFloat("right") class="edui-clickable">' + editor.getLang("justifyright") + "</span>&nbsp;&nbsp;" + '<span onclick=$$._onImgSetFloat("center") class="edui-clickable">' + editor.getLang("justifycenter") + "</span>&nbsp;&nbsp;" + "<span onclick=\"$$._onImgEditButtonClick('" + dialogName + '\');" class="edui-clickable">' + editor.getLang("modify") + "</span></nobr>";
                            !html && (html = popup.formatHtml(str))
                        }
                        if (editor.ui._dialogs.linkDialog) {
                            var link = editor.queryCommandValue("link");
                            var url;
                            if (link && (url = (link.getAttribute("_href") || link.getAttribute("href", 2)))) {
                                var txt = url;
                                if (url.length > 30) {
                                    txt = url.substring(0, 20) + "..."
                                }
                                if (html) {
                                    html += '<div style="height:5px;"></div>'
                                }
                                html += popup.formatHtml("<nobr>" + editor.getLang("anthorMsg") + ': <a target="_blank" href="' + url + '" title="' + url + '" >' + txt + "</a>" + ' <span class="edui-clickable" onclick="$$._onEditButtonClick();">' + editor.getLang("modify") + "</span>" + ' <span class="edui-clickable" onclick="$$._onRemoveButtonClick(\'unlink\');"> ' + editor.getLang("clear") + "</span></nobr>");
                                popup.showAnchor(link)
                            }
                        }
                        if (html) {
                            popup.getDom("content").innerHTML = html;
                            popup.anchorEl = img || link;
                            popup.showAnchor(popup.anchorEl)
                        } else {
                            popup.hide()
                        }
                    })
                }
            },
            _initToolbars: function() {
                var editor = this.editor;
                var toolbars = this.toolbars || [];
                var toolbarUis = [];
                for (var i = 0; i < toolbars.length; i++) {
                    var toolbar = toolbars[i];
                    var toolbarUi = new baidu.editor.ui.Toolbar({
                        theme: editor.options.theme
                    });
                    for (var j = 0; j < toolbar.length; j++) {
                        var toolbarItem = toolbar[j];
                        var toolbarItemUi = null;
                        if (typeof toolbarItem == "string") {
                            toolbarItem = toolbarItem.toLowerCase();
                            if (toolbarItem == "|") {
                                toolbarItem = "Separator"
                            }
                            if (toolbarItem == "||") {
                                toolbarItem = "Breakline"
                            }
                            if (baidu.editor.ui[toolbarItem]) {
                                toolbarItemUi = new baidu.editor.ui[toolbarItem](editor)
                            }
                            if (toolbarItem == "fullscreen") {
                                if (toolbarUis && toolbarUis[0]) {
                                    toolbarUis[0].items.splice(0, 0, toolbarItemUi)
                                } else {
                                    toolbarItemUi && toolbarUi.items.splice(0, 0, toolbarItemUi)
                                }
                                continue
                            }
                        } else {
                            toolbarItemUi = toolbarItem
                        }
                        if (toolbarItemUi && toolbarItemUi.id) {
                            toolbarUi.add(toolbarItemUi)
                        }
                    }
                    toolbarUis[i] = toolbarUi
                }
                utils.each(UE._customizeUI, function(obj, key) {
                    var itemUI, index;
                    if (obj.id && obj.id != editor.key) {
                        return false
                    }
                    itemUI = obj.execFn.call(editor, editor, key);
                    if (itemUI) {
                        index = obj.index;
                        if (index === undefined) {
                            index = toolbarUi.items.length
                        }
                        toolbarUi.add(itemUI, index)
                    }
                });
                this.toolbars = toolbarUis
            },
            getHtmlTpl: function() {
                return '<div id="##" class="%%">' + '<div id="##_toolbarbox" class="%%-toolbarbox">' + (this.toolbars.length ? '<div id="##_toolbarboxouter" class="%%-toolbarboxouter"><div class="%%-toolbarboxinner">' + this.renderToolbarBoxHtml() + "</div></div>" : "") + '<div id="##_toolbarmsg" class="%%-toolbarmsg" style="display:none;">' + '<div id = "##_upload_dialog" class="%%-toolbarmsg-upload" onclick="$$.showWordImageDialog();">' + this.editor.getLang("clickToUpload") + "</div>" + '<div class="%%-toolbarmsg-close" onclick="$$.hideToolbarMsg();">x</div>' + '<div id="##_toolbarmsg_label" class="%%-toolbarmsg-label"></div>' + '<div style="height:0;overflow:hidden;clear:both;"></div>' + "</div>" + '<div id="##_message_holder" class="%%-messageholder"></div>' + "</div>" + '<div id="##_iframeholder" class="%%-iframeholder">' + "</div>" + '<div id="##_bottombar" class="%%-bottomContainer"><table><tr>' + '<td id="##_elementpath" class="%%-bottombar"></td>' + '<td id="##_wordcount" class="%%-wordcount"></td>' + '<td id="##_scale" class="%%-scale"><div class="%%-icon"></div></td>' + "</tr></table></div>" + '<div id="##_scalelayer"></div>' + "</div>"
            },
            showWordImageDialog: function() {
                this._dialogs["wordimageDialog"].open()
            },
            renderToolbarBoxHtml: function() {
                var buff = [];
                for (var i = 0; i < this.toolbars.length; i++) {
                    buff.push(this.toolbars[i].renderHtml())
                }
                return buff.join("")
            },
            setFullScreen: function(fullscreen) {
                var editor = this.editor,
                    container = editor.container.parentNode.parentNode;
                if (this._fullscreen != fullscreen) {
                    this._fullscreen = fullscreen;
                    this.editor.fireEvent("beforefullscreenchange", fullscreen);
                    if (baidu.editor.browser.gecko) {
                        var bk = editor.selection.getRange().createBookmark()
                    }
                    if (fullscreen) {
                        while (container.tagName != "BODY") {
                            var position = baidu.editor.dom.domUtils.getComputedStyle(container, "position");
                            nodeStack.push(position);
                            container.style.position = "static";
                            container = container.parentNode
                        }
                        this._bakHtmlOverflow = document.documentElement.style.overflow;
                        this._bakBodyOverflow = document.body.style.overflow;
                        this._bakAutoHeight = this.editor.autoHeightEnabled;
                        this._bakScrollTop = Math.max(document.documentElement.scrollTop, document.body.scrollTop);
                        this._bakEditorContaninerWidth = editor.iframe.parentNode.offsetWidth;
                        if (this._bakAutoHeight) {
                            editor.autoHeightEnabled = false;
                            this.editor.disableAutoHeight()
                        }
                        document.documentElement.style.overflow = "hidden";
                        window.scrollTo(0, window.scrollY);
                        this._bakCssText = this.getDom().style.cssText;
                        this._bakCssText1 = this.getDom("iframeholder").style.cssText;
                        editor.iframe.parentNode.style.width = "";
                        this._updateFullScreen()
                    } else {
                        while (container.tagName != "BODY") {
                            container.style.position = nodeStack.shift();
                            container = container.parentNode
                        }
                        this.getDom().style.cssText = this._bakCssText;
                        this.getDom("iframeholder").style.cssText = this._bakCssText1;
                        if (this._bakAutoHeight) {
                            editor.autoHeightEnabled = true;
                            this.editor.enableAutoHeight()
                        }
                        document.documentElement.style.overflow = this._bakHtmlOverflow;
                        document.body.style.overflow = this._bakBodyOverflow;
                        editor.iframe.parentNode.style.width = this._bakEditorContaninerWidth + "px";
                        window.scrollTo(0, this._bakScrollTop)
                    }
                    if (browser.gecko && editor.body.contentEditable === "true") {
                        var input = document.createElement("input");
                        document.body.appendChild(input);
                        editor.body.contentEditable = false;
                        setTimeout(function() {
                            input.focus();
                            setTimeout(function() {
                                editor.body.contentEditable = true;
                                editor.fireEvent("fullscreenchanged", fullscreen);
                                editor.selection.getRange().moveToBookmark(bk).select(true);
                                baidu.editor.dom.domUtils.remove(input);
                                fullscreen && window.scroll(0, 0)
                            }, 0)
                        }, 0)
                    }
                    if (editor.body.contentEditable === "true") {
                        this.editor.fireEvent("fullscreenchanged", fullscreen);
                        this.triggerLayout()
                    }
                }
            },
            _updateFullScreen: function() {
                if (this._fullscreen) {
                    var vpRect = uiUtils.getViewportRect();
                    this.getDom().style.cssText = "border:0;position:absolute;left:0;top:" + (this.editor.options.topOffset || 0) + "px;width:" + vpRect.width + "px;height:" + vpRect.height + "px;z-index:" + (this.getDom().style.zIndex * 1 + 100);
                    uiUtils.setViewportOffset(this.getDom(), {
                        left: 0,
                        top: this.editor.options.topOffset || 0
                    });
                    this.editor.setHeight(vpRect.height - this.getDom("toolbarbox").offsetHeight - this.getDom("bottombar").offsetHeight - (this.editor.options.topOffset || 0), true);
                    if (browser.gecko) {
                        try {
                            window.onresize()
                        } catch (e) {}
                    }
                }
            },
            _updateElementPath: function() {
                var bottom = this.getDom("elementpath"),
                    list;
                if (this.elementPathEnabled && (list = this.editor.queryCommandValue("elementpath"))) {
                    var buff = [];
                    for (var i = 0, ci; ci = list[i]; i++) {
                        buff[i] = this.formatHtml('<span unselectable="on" onclick="$$.editor.execCommand(&quot;elementpath&quot;, &quot;' + i + '&quot;);">' + ci + "</span>")
                    }
                    bottom.innerHTML = '<div class="edui-editor-breadcrumb" onmousedown="return false;">' + this.editor.getLang("elementPathTip") + ": " + buff.join(" &gt; ") + "</div>"
                } else {
                    bottom.style.display = "none"
                }
            },
            disableElementPath: function() {
                var bottom = this.getDom("elementpath");
                bottom.innerHTML = "";
                bottom.style.display = "none";
                this.elementPathEnabled = false
            },
            enableElementPath: function() {
                var bottom = this.getDom("elementpath");
                bottom.style.display = "";
                this.elementPathEnabled = true;
                this._updateElementPath()
            },
            _scale: function() {
                var doc = document,
                    editor = this.editor,
                    editorHolder = editor.container,
                    editorDocument = editor.document,
                    toolbarBox = this.getDom("toolbarbox"),
                    bottombar = this.getDom("bottombar"),
                    scale = this.getDom("scale"),
                    scalelayer = this.getDom("scalelayer");
                var isMouseMove = false,
                    position = null,
                    minEditorHeight = 0,
                    minEditorWidth = editor.options.minFrameWidth,
                    pageX = 0,
                    pageY = 0,
                    scaleWidth = 0,
                    scaleHeight = 0;

                function down() {
                    position = domUtils.getXY(editorHolder);
                    if (!minEditorHeight) {
                        minEditorHeight = editor.options.minFrameHeight + toolbarBox.offsetHeight + bottombar.offsetHeight
                    }
                    scalelayer.style.cssText = "position:absolute;left:0;display:;top:0;background-color:#41ABFF;opacity:0.4;filter: Alpha(opacity=40);width:" + editorHolder.offsetWidth + "px;height:" + editorHolder.offsetHeight + "px;z-index:" + (editor.options.zIndex + 1);
                    domUtils.on(doc, "mousemove", move);
                    domUtils.on(editorDocument, "mouseup", up);
                    domUtils.on(doc, "mouseup", up)
                }
                var me = this;
                this.editor.addListener("fullscreenchanged", function(e, fullScreen) {
                    if (fullScreen) {
                        me.disableScale()
                    } else {
                        if (me.editor.options.scaleEnabled) {
                            me.enableScale();
                            var tmpNode = me.editor.document.createElement("span");
                            me.editor.body.appendChild(tmpNode);
                            me.editor.body.style.height = Math.max(domUtils.getXY(tmpNode).y, me.editor.iframe.offsetHeight - 20) + "px";
                            domUtils.remove(tmpNode)
                        }
                    }
                });

                function move(event) {
                    clearSelection();
                    var e = event || window.event;
                    pageX = e.pageX || (doc.documentElement.scrollLeft + e.clientX);
                    pageY = e.pageY || (doc.documentElement.scrollTop + e.clientY);
                    scaleWidth = pageX - position.x;
                    scaleHeight = pageY - position.y;
                    if (scaleWidth >= minEditorWidth) {
                        isMouseMove = true;
                        scalelayer.style.width = scaleWidth + "px"
                    }
                    if (scaleHeight >= minEditorHeight) {
                        isMouseMove = true;
                        scalelayer.style.height = scaleHeight + "px"
                    }
                }
                function up() {
                    if (isMouseMove) {
                        isMouseMove = false;
                        editor.ui._actualFrameWidth = scalelayer.offsetWidth - 2;
                        editorHolder.style.width = editor.ui._actualFrameWidth + "px";
                        editor.setHeight(scalelayer.offsetHeight - bottombar.offsetHeight - toolbarBox.offsetHeight - 2, true)
                    }
                    if (scalelayer) {
                        scalelayer.style.display = "none"
                    }
                    clearSelection();
                    domUtils.un(doc, "mousemove", move);
                    domUtils.un(editorDocument, "mouseup", up);
                    domUtils.un(doc, "mouseup", up)
                }
                function clearSelection() {
                    if (browser.ie) {
                        doc.selection.clear()
                    } else {
                        window.getSelection().removeAllRanges()
                    }
                }
                this.enableScale = function() {
                    if (editor.queryCommandState("source") == 1) {
                        return
                    }
                    scale.style.display = "";
                    this.scaleEnabled = true;
                    domUtils.on(scale, "mousedown", down)
                };
                this.disableScale = function() {
                    scale.style.display = "none";
                    this.scaleEnabled = false;
                    domUtils.un(scale, "mousedown", down)
                }
            },
            isFullScreen: function() {
                return this._fullscreen
            },
            postRender: function() {
                UIBase.prototype.postRender.call(this);
                for (var i = 0; i < this.toolbars.length; i++) {
                    this.toolbars[i].postRender()
                }
                var me = this;
                var timerId, domUtils = baidu.editor.dom.domUtils,
                    updateFullScreenTime = function() {
                        clearTimeout(timerId);
                        timerId = setTimeout(function() {
                            me._updateFullScreen()
                        })
                    };
                domUtils.on(window, "resize", updateFullScreenTime);
                me.addListener("destroy", function() {
                    domUtils.un(window, "resize", updateFullScreenTime);
                    clearTimeout(timerId)
                })
            },
            showToolbarMsg: function(msg, flag) {
                this.getDom("toolbarmsg_label").innerHTML = msg;
                this.getDom("toolbarmsg").style.display = "";
                if (!flag) {
                    var w = this.getDom("upload_dialog");
                    w.style.display = "none"
                }
            },
            hideToolbarMsg: function() {
                this.getDom("toolbarmsg").style.display = "none"
            },
            mapUrl: function(url) {
                return url ? url.replace("~/", this.editor.options.UEDITOR_HOME_URL || "") : ""
            },
            triggerLayout: function() {
                var dom = this.getDom();
                if (dom.style.zoom == "1") {
                    dom.style.zoom = "100%"
                } else {
                    dom.style.zoom = "1"
                }
            }
        };
        utils.inherits(EditorUI, baidu.editor.ui.UIBase);
        var instances = {};
        UE.ui.Editor = function(options) {
            var editor = new UE.Editor(options);
            editor.options.editor = editor;
            utils.loadFile(document, {
                href: editor.options.themePath + editor.options.theme + "/css/ueditor.css",
                tag: "link",
                type: "text/css",
                rel: "stylesheet"
            });
            var oldRender = editor.render;
            editor.render = function(holder) {
                if (holder.constructor === String) {
                    editor.key = holder;
                    instances[holder] = editor
                }
                utils.domReady(function() {
                    editor.langIsReady ? renderUI() : editor.addListener("langReady", renderUI);

                    function renderUI() {
                        editor.setOpt({
                            labelMap: editor.options.labelMap || editor.getLang("labelMap")
                        });
                        new EditorUI(editor.options);
                        if (holder) {
                            if (holder.constructor === String) {
                                holder = document.getElementById(holder)
                            }
                            holder && holder.getAttribute("name") && (editor.options.textarea = holder.getAttribute("name"));
                            if (holder && /script|textarea/ig.test(holder.tagName)) {
                                var newDiv = document.createElement("div");
                                holder.parentNode.insertBefore(newDiv, holder);
                                var cont = holder.value || holder.innerHTML;
                                editor.options.initialContent = /^[\t\r\n ]*$/.test(cont) ? editor.options.initialContent : cont.replace(/>[\n\r\t]+([ ]{4})+/g, ">").replace(/[\n\r\t]+([ ]{4})+</g, "<").replace(/>[\n\r\t]+</g, "><");
                                holder.className && (newDiv.className = holder.className);
                                holder.style.cssText && (newDiv.style.cssText = holder.style.cssText);
                                if (/textarea/i.test(holder.tagName)) {
                                    editor.textarea = holder;
                                    editor.textarea.style.display = "none"
                                } else {
                                    holder.parentNode.removeChild(holder)
                                }
                                if (holder.id) {
                                    newDiv.id = holder.id;
                                    domUtils.removeAttributes(holder, "id")
                                }
                                holder = newDiv;
                                holder.innerHTML = ""
                            }
                        }
                        domUtils.addClass(holder, "edui-" + editor.options.theme);
                        editor.ui.render(holder);
                        var opt = editor.options;
                        editor.container = editor.ui.getDom();
                        var parents = domUtils.findParents(holder, true);
                        var displays = [];
                        for (var i = 0, ci; ci = parents[i]; i++) {
                            displays[i] = ci.style.display;
                            ci.style.display = "block"
                        }
                        if (opt.initialFrameWidth) {
                            opt.minFrameWidth = opt.initialFrameWidth
                        } else {
                            opt.minFrameWidth = opt.initialFrameWidth = holder.offsetWidth;
                            var styleWidth = holder.style.width;
                            if (/%$/.test(styleWidth)) {
                                opt.initialFrameWidth = styleWidth
                            }
                        }
                        if (opt.initialFrameHeight) {
                            opt.minFrameHeight = opt.initialFrameHeight
                        } else {
                            opt.initialFrameHeight = opt.minFrameHeight = holder.offsetHeight
                        }
                        for (var i = 0, ci; ci = parents[i]; i++) {
                            ci.style.display = displays[i]
                        }
                        if (holder.style.height) {
                            holder.style.height = ""
                        }
                        editor.container.style.width = opt.initialFrameWidth + (/%$/.test(opt.initialFrameWidth) ? "" : "px");
                        editor.container.style.zIndex = opt.zIndex;
                        oldRender.call(editor, editor.ui.getDom("iframeholder"));
                        editor.fireEvent("afteruiready")
                    }
                })
            };
            return editor
        };
        UE.getEditor = function(id, opt) {
            var editor = instances[id];
            if (!editor) {
                editor = instances[id] = new UE.ui.Editor(opt);
                editor.render(id)
            }
            return editor
        };
        UE.delEditor = function(id) {
            var editor;
            if (editor = instances[id]) {
                editor.key && editor.destroy();
                delete instances[id]
            }
        };
        UE.registerUI = function(uiName, fn, index, editorId) {
            utils.each(uiName.split(/\s+/), function(name) {
                UE._customizeUI[name] = {
                    id: editorId,
                    execFn: fn,
                    index: index
                }
            })
        }
    })();
    UE.registerUI("message", function(editor) {
        var editorui = baidu.editor.ui;
        var Message = editorui.Message;
        var holder;
        var _messageItems = [];
        var me = editor;
        me.addListener("ready", function() {
            holder = document.getElementById(me.ui.id + "_message_holder");
            updateHolderPos();
            setTimeout(function() {
                updateHolderPos()
            }, 500)
        });
        me.addListener("showmessage", function(type, opt) {
            opt = utils.isString(opt) ? {
                "content": opt
            } : opt;
            var message = new Message({
                    "timeout": opt.timeout,
                    "type": opt.type,
                    "content": opt.content,
                    "keepshow": opt.keepshow,
                    "editor": me
                }),
                mid = opt.id || ("msg_" + (+new Date()).toString(36));
            message.render(holder);
            _messageItems[mid] = message;
            message.reset(opt);
            updateHolderPos();
            return mid
        });
        me.addListener("updatemessage", function(type, id, opt) {
            opt = utils.isString(opt) ? {
                "content": opt
            } : opt;
            var message = _messageItems[id];
            message.render(holder);
            message && message.reset(opt)
        });
        me.addListener("hidemessage", function(type, id) {
            var message = _messageItems[id];
            message && message.hide()
        });

        function updateHolderPos() {
            var toolbarbox = me.ui.getDom("toolbarbox");
            if (toolbarbox) {
                holder.style.top = toolbarbox.offsetHeight + 3 + "px"
            }
            holder.style.zIndex = Math.max(me.options.zIndex, me.iframe.style.zIndex) + 1
        }
    });
    UE.registerUI("autosave", function(editor) {
        var timer = null,
            uid = null;
        editor.on("afterautosave", function() {
            clearTimeout(timer);
            timer = setTimeout(function() {
                if (uid) {
                    editor.trigger("hidemessage", uid)
                }
                uid = editor.trigger("showmessage", {
                    content: editor.getLang("autosave.success"),
                    timeout: 2000
                })
            }, 2000)
        })
    })
})(); /*   美化：格式化代码，使之容易阅读			*/
/*   净化：去掉代码中多余的注释、换行、空格等	*/
/*   压缩：将代码压缩为更小体积，便于传输		*/
/*   解压：将压缩后的代码转换为人可以阅读的格式	*/
/*   混淆：将代码的中变量名简短化以减小体积，但可读性差，经混淆后的代码无法还原	*/

/*   如果有用，请别忘了推荐给你的朋友：		*/
/*   javascript在线美化、净化、压缩、解压：https://tool.lu/js   */

/*   以下是演示代码				*/
var Inote = {};
Inote.JSTool = function(options) {
    this.options = options || {};
};
Inote.JSTool.prototype = {
    _name: 'Javascript工具',
    _history: {
        'v1.0': ['2011-01-18', 'javascript工具上线'],
        'v1.1': ['2012-03-23', '增加混淆功能'],
        'v1.2': ['2012-07-21', '升级美化功能引擎'],
        'v1.3': ['2014-03-01', '升级解密功能，支持eval,window.eval,window["eval"]等的解密'],
        'v1.4': ['2014-08-05', '升级混淆功能引擎'],
        'v1.5': ['2014-08-09', '升级js压缩引擎'],
        'v1.6': ['2015-04-11', '升级js混淆引擎'],
        'v1.7': ['2017-02-12', '升级js混淆引擎']
    },
    options: {},
    getName: function() {
        return this._name;
    },
    getHistory: function() {
        return this._history;
    }
};
var jstool = new Inote.JSTool();